| author | Henrik Lynggaard Hansen | 2012-07-16 15:08:20 (EDT) |
|---|---|---|
| committer | Henrik Lynggaard Hansen | 2012-07-16 15:08:20 (EDT) |
| commit | ff1907164ab1b72bd101eb9aedfb8aab1b35921d (patch) (side-by-side diff) | |
| tree | 29a7d48ef2786e2ce9eb3193262a8eb18ac1348f | |
| parent | 2e3f55d880a7c54c95afb2f243678f960c79c6bf (diff) | |
| download | org.eclipse.hudson.core-ff1907164ab1b72bd101eb9aedfb8aab1b35921d.zip org.eclipse.hudson.core-ff1907164ab1b72bd101eb9aedfb8aab1b35921d.tar.gz org.eclipse.hudson.core-ff1907164ab1b72bd101eb9aedfb8aab1b35921d.tar.bz2 | |
Reformat main hudson packagerefs/changes/02/6802/1
Change-Id: I4133dffc47cd918a7fcf6599878a8ea111c5ee0b
Signed-off-by: Henrik Lynggaard Hansen <henrik@hlyh.dk>
47 files changed, 1948 insertions, 1902 deletions
diff --git a/hudson-core/src/main/java/hudson/AbortException.java b/hudson-core/src/main/java/hudson/AbortException.java index 111079c..4592512 100644 --- a/hudson-core/src/main/java/hudson/AbortException.java +++ b/hudson-core/src/main/java/hudson/AbortException.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi - * + * *******************************************************************************/ package hudson; @@ -18,23 +18,24 @@ package hudson; import java.io.IOException; /** - * Signals a failure where the error was anticipated and diagnosed. - * When this exception is caught, - * the stack trace will not be printed, and the build will be marked as a failure. + * Signals a failure where the error was anticipated and diagnosed. When this + * exception is caught, the stack trace will not be printed, and the build will + * be marked as a failure. * * @author Kohsuke Kawaguchi -*/ + */ public final class AbortException extends IOException { + public AbortException() { } /** * When this exception is caught, the specified message will be reported. + * * @since 1.298 */ public AbortException(String message) { super(message); } - private static final long serialVersionUID = 1L; } diff --git a/hudson-core/src/main/java/hudson/AbstractMarkupText.java b/hudson-core/src/main/java/hudson/AbstractMarkupText.java index 70bc039..31c6277 100644 --- a/hudson-core/src/main/java/hudson/AbstractMarkupText.java +++ b/hudson-core/src/main/java/hudson/AbstractMarkupText.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -26,19 +26,19 @@ import java.util.regex.Matcher; /** * Common part between {@link MarkupText} and {@link MarkupText.SubText}. * - * <p> - * See {@link MarkupText} for more discussion about what this class represents. + * <p> See {@link MarkupText} for more discussion about what this class + * represents. * * @author Kohsuke Kawaguchi * @since 1.250 */ public abstract class AbstractMarkupText { - /*package*/ AbstractMarkupText() {} // limit who can subclass this type. - + /*package*/ AbstractMarkupText() { + } // limit who can subclass this type. /** - * Returns the plain text portion of this {@link MarkupText} without - * any markup, nor any escape. + * Returns the plain text portion of this {@link MarkupText} without any + * markup, nor any escape. */ public abstract String getText(); @@ -56,51 +56,51 @@ public abstract class AbstractMarkupText { /** * Returns a subtext. * - * @param end - * If negative, -N means "trim the last N-1 chars". That is, (s,-1) is the same as (s,length) + * @param end If negative, -N means "trim the last N-1 chars". That is, + * (s,-1) is the same as (s,length) */ public abstract MarkupText.SubText subText(int start, int end); /** * Adds a start tag and end tag at the specified position. * - * <p> - * For example, if the text was "abc", then <tt>addMarkup(1,2,"<b>","</b>")</tt> - * would generate <tt>"a<b>b</b>c"</tt> + * <p> For example, if the text was "abc", then + * <tt>addMarkup(1,2,"<b>","</b>")</tt> would generate + * <tt>"a<b>b</b>c"</tt> */ - public abstract void addMarkup( int startPos, int endPos, String startTag, String endTag ); + public abstract void addMarkup(int startPos, int endPos, String startTag, String endTag); /** * Inserts an A tag that surrounds the given position. * * @since 1.349 */ - public void addHyperlink( int startPos, int endPos, String url ) { - addMarkup(startPos,endPos,"<a href='"+url+"'>","</a>"); + public void addHyperlink(int startPos, int endPos, String url) { + addMarkup(startPos, endPos, "<a href='" + url + "'>", "</a>"); } /** - * Inserts an A tag that surrounds the given position. - * But this hyperlink is less visible. + * Inserts an A tag that surrounds the given position. But this hyperlink is + * less visible. * * @since 1.395 */ - public void addHyperlinkLowKey( int startPos, int endPos, String url ) { - addMarkup(startPos,endPos,"<a class='lowkey' href='"+url+"'>","</a>"); + public void addHyperlinkLowKey(int startPos, int endPos, String url) { + addMarkup(startPos, endPos, "<a class='lowkey' href='" + url + "'>", "</a>"); } /** * Hides the given text. */ - public void hide( int startPos, int endPos ) { - addMarkup(startPos,endPos,"<span style='display:none'>","</span>"); + public void hide(int startPos, int endPos) { + addMarkup(startPos, endPos, "<span style='display:none'>", "</span>"); } /** * Adds a start tag and end tag around the entire text */ public final void wrapBy(String startTag, String endTag) { - addMarkup(0,length(),startTag,endTag); + addMarkup(0, length(), startTag, endTag); } /** @@ -112,8 +112,9 @@ public abstract class AbstractMarkupText { String text = getText(); Matcher m = pattern.matcher(text); - if(m.find()) + if (m.find()) { return createSubText(m); + } return null; } @@ -121,33 +122,35 @@ public abstract class AbstractMarkupText { /** * Find all "tokens" that match the given pattern in this text. * - * <p> - * A token is like a substring, except that it's aware of word boundaries. - * For example, while "bc" is a string of "abc", calling {@code findTokens} - * with "bc" as a pattern on string "abc" won't match anything. + * <p> A token is like a substring, except that it's aware of word + * boundaries. For example, while "bc" is a string of "abc", calling + * {@code findTokens} with "bc" as a pattern on string "abc" won't match + * anything. * - * <p> - * This method is convenient for finding keywords that follow a certain syntax - * from natural text. You can then use {@link MarkupText.SubText#surroundWith(String,String)} - * to put mark up around such text. + * <p> This method is convenient for finding keywords that follow a certain + * syntax from natural text. You can then use + * {@link MarkupText.SubText#surroundWith(String,String)} to put mark up + * around such text. */ public List<MarkupText.SubText> findTokens(Pattern pattern) { String text = getText(); Matcher m = pattern.matcher(text); List<SubText> r = new ArrayList<SubText>(); - while(m.find()) { + while (m.find()) { int idx = m.start(); - if(idx>0) { - char ch = text.charAt(idx-1); - if(Character.isLetter(ch) || Character.isDigit(ch)) + if (idx > 0) { + char ch = text.charAt(idx - 1); + if (Character.isLetter(ch) || Character.isDigit(ch)) { continue; // not at a word boundary + } } idx = m.end(); - if(idx<text.length()) { + if (idx < text.length()) { char ch = text.charAt(idx); - if(Character.isLetter(ch) || Character.isDigit(ch)) + if (Character.isLetter(ch) || Character.isDigit(ch)) { continue; // not at a word boundary + } } r.add(createSubText(m)); } diff --git a/hudson-core/src/main/java/hudson/BulkChange.java b/hudson-core/src/main/java/hudson/BulkChange.java index a47187f..5c4f4ab 100644 --- a/hudson-core/src/main/java/hudson/BulkChange.java +++ b/hudson-core/src/main/java/hudson/BulkChange.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -22,11 +22,11 @@ import hudson.model.Hudson; import java.io.IOException; /** - * Transaction-like object that can be used to make a bunch of changes to an object, and defer the - * {@link Saveable#save()} until the end. + * Transaction-like object that can be used to make a bunch of changes to an + * object, and defer the {@link Saveable#save()} until the end. * - * <p> - * The usage of {@link BulkChange} needs to follow a specific closure-like pattern, namely: + * <p> The usage of {@link BulkChange} needs to follow a specific closure-like + * pattern, namely: * * <pre> * BulkChange bc = new BulkChange(someObject); @@ -37,8 +37,7 @@ import java.io.IOException; * } * </pre> * - * <p> - * ... or if you'd like to avoid saving when something bad happens: + * <p> ... or if you'd like to avoid saving when something bad happens: * * <pre> * BulkChange bc = new BulkChange(someObject); @@ -50,33 +49,30 @@ import java.io.IOException; * } * </pre> * - * <p> - * Use of this method is optional. If {@link BulkChange} is not used, individual mutator - * will perform the save operation, and things will just run somewhat slower. + * <p> Use of this method is optional. If {@link BulkChange} is not used, + * individual mutator will perform the save operation, and things will just run + * somewhat slower. * * - * <h2>Cooperation from {@link Saveable}</h2> - * <p> - * For this class to work as intended, {@link Saveable} implementations need to co-operate. - * Namely, + * <h2>Cooperation from {@link Saveable}</h2> <p> For this class to work as + * intended, {@link Saveable} implementations need to co-operate. Namely, * - * <ol> - * <li> - * Mutater methods should invoke {@code this.save()} so that if the method is called outside - * a {@link BulkChange}, the result will be saved immediately. + * <ol> <li> Mutater methods should invoke {@code this.save()} so that if the + * method is called outside a {@link BulkChange}, the result will be saved + * immediately. * - * <li> - * In the {@code save()} method implementation, use {@link #contains(Saveable)} and - * only perform the actual I/O operation when this method returns false. - * </ol> + * <li> In the {@code save()} method implementation, use + * {@link #contains(Saveable)} and only perform the actual I/O operation when + * this method returns false. </ol> * - * <p> - * See {@link Hudson#save()} as an example if you are not sure how to implement {@link Saveable}. + * <p> See {@link Hudson#save()} as an example if you are not sure how to + * implement {@link Saveable}. * * @author Kohsuke Kawaguchi * @since 1.249 */ public class BulkChange { + private final Saveable saveable; //TODO: review and check whether we can do it private public final Exception allocator; @@ -84,9 +80,7 @@ public class BulkChange { public Exception getAllocator() { return allocator; } - private final BulkChange parent; - private boolean completed; public BulkChange(Saveable saveable) { @@ -104,7 +98,9 @@ public class BulkChange { * Saves the accumulated changes. */ public void commit() throws IOException { - if(completed) return; + if (completed) { + return; + } completed = true; // move this object out of the scope first before save, or otherwise the save() method will do nothing. @@ -115,33 +111,36 @@ public class BulkChange { /** * Exits the scope of {@link BulkChange} without saving the changes. * - * <p> - * This can be used when a bulk change fails in the middle. - * Note that unlike a real transaction, this will not roll back the state of the object. + * <p> This can be used when a bulk change fails in the middle. Note that + * unlike a real transaction, this will not roll back the state of the + * object. * - * <p> - * The abort method can be called after the commit method, in which case this method does nothing. - * This is so that {@link BulkChange} can be used naturally in the try/finally block. + * <p> The abort method can be called after the commit method, in which case + * this method does nothing. This is so that {@link BulkChange} can be used + * naturally in the try/finally block. */ public void abort() { - if(completed) return; + if (completed) { + return; + } completed = true; pop(); } private void pop() { - if(current()!=this) + if (current() != this) { throw new AssertionError("Trying to save BulkChange that's not in scope"); + } INSCOPE.set(parent); } - /** * {@link BulkChange}s that are effective currently. */ private static final ThreadLocal<BulkChange> INSCOPE = new ThreadLocal<BulkChange>(); /** - * Gets the {@link BulkChange} instance currently in scope for the current thread. + * Gets the {@link BulkChange} instance currently in scope for the current + * thread. */ public static BulkChange current() { return INSCOPE.get(); @@ -150,21 +149,21 @@ public class BulkChange { /** * Checks if the given {@link Saveable} is currently in the bulk change. * - * <p> - * The expected usage is from the {@link Saveable#save()} implementation to check - * if the actual persistence should happen now or not. + * <p> The expected usage is from the {@link Saveable#save()} implementation + * to check if the actual persistence should happen now or not. */ public static boolean contains(Saveable s) { - for(BulkChange b=current(); b!=null; b=b.parent) - if(b.saveable==s || b.saveable==ALL) + for (BulkChange b = current(); b != null; b = b.parent) { + if (b.saveable == s || b.saveable == ALL) { return true; + } + } return false; } - /** - * Magic {@link Saveable} instance that can make {@link BulkChange} veto - * all the save operations by making the {@link #contains(Saveable)} method return - * true for everything. + * Magic {@link Saveable} instance that can make {@link BulkChange} veto all + * the save operations by making the {@link #contains(Saveable)} method + * return true for everything. */ public static final Saveable ALL = new Saveable() { public void save() { diff --git a/hudson-core/src/main/java/hudson/ClassicPluginStrategy.java b/hudson-core/src/main/java/hudson/ClassicPluginStrategy.java index 98a157b..8c92326 100644 --- a/hudson-core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/hudson-core/src/main/java/hudson/ClassicPluginStrategy.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, Jean-Baptiste Quenot, Tom Huybrechts - * + * Contributors: + * + * Kohsuke Kawaguchi, Jean-Baptiste Quenot, Tom Huybrechts + * * *******************************************************************************/ @@ -53,16 +53,14 @@ import org.apache.tools.ant.types.FileSet; public class ClassicPluginStrategy implements PluginStrategy { private static final Logger LOGGER = Logger.getLogger(ClassicPluginStrategy.class.getName()); - /** * Filter for jar files. */ private static final FilenameFilter JAR_FILTER = new FilenameFilter() { - public boolean accept(File dir,String name) { + public boolean accept(File dir, String name) { return name.endsWith(".jar"); } }; - private PluginManager pluginManager; public ClassicPluginStrategy(PluginManager pluginManager) { @@ -108,7 +106,7 @@ public class ClassicPluginStrategy implements PluginStrategy { if (!manifestFile.exists()) { throw new IOException( "Plugin installation failed. No manifest at " - + manifestFile); + + manifestFile); } FileInputStream fin = new FileInputStream(manifestFile); try { @@ -128,15 +126,17 @@ public class ClassicPluginStrategy implements PluginStrategy { parseClassPath(manifest, archive, paths, "Libraries", ","); parseClassPath(manifest, archive, paths, "Class-Path", " +"); // backward compatibility - baseResourceURL = resolve(archive,atts.getValue("Resource-Path")).toURI().toURL(); + baseResourceURL = resolve(archive, atts.getValue("Resource-Path")).toURI().toURL(); } else { File classes = new File(expandDir, "WEB-INF/classes"); - if (classes.exists()) + if (classes.exists()) { paths.add(classes); + } File lib = new File(expandDir, "WEB-INF/lib"); File[] libs = lib.listFiles(JAR_FILTER); - if (libs != null) + if (libs != null) { paths.addAll(Arrays.asList(libs)); + } baseResourceURL = expandDir.toURI().toURL(); } @@ -159,35 +159,37 @@ public class ClassicPluginStrategy implements PluginStrategy { } } } - for (DetachedPlugin detached : DETACHED_LIST) - detached.fix(atts,optionalDependencies); + for (DetachedPlugin detached : DETACHED_LIST) { + detached.fix(atts, optionalDependencies); + } - ClassLoader dependencyLoader = new DependencyClassLoader(getBaseClassLoader(atts), archive, Util.join(dependencies,optionalDependencies)); + ClassLoader dependencyLoader = new DependencyClassLoader(getBaseClassLoader(atts), archive, Util.join(dependencies, optionalDependencies)); return new PluginWrapper(pluginManager, archive, manifest, baseResourceURL, createClassLoader(paths, dependencyLoader, atts), disableFile, dependencies, optionalDependencies); } - + @Deprecated protected ClassLoader createClassLoader(List<File> paths, ClassLoader parent) throws IOException { - return createClassLoader( paths, parent, null ); + return createClassLoader(paths, parent, null); } /** - * Creates the classloader that can load all the specified jar files and delegate to the given parent. + * Creates the classloader that can load all the specified jar files and + * delegate to the given parent. */ protected ClassLoader createClassLoader(List<File> paths, ClassLoader parent, Attributes atts) throws IOException { if (atts != null) { - String usePluginFirstClassLoader = atts.getValue( "PluginFirstClassLoader" ); - if (Boolean.valueOf( usePluginFirstClassLoader )) { + String usePluginFirstClassLoader = atts.getValue("PluginFirstClassLoader"); + if (Boolean.valueOf(usePluginFirstClassLoader)) { PluginFirstClassLoader classLoader = new PluginFirstClassLoader(); - classLoader.setParentFirst( false ); - classLoader.setParent( parent ); - classLoader.addPathFiles( paths ); + classLoader.setParentFirst(false); + classLoader.setParent(parent); + classLoader.addPathFiles(paths); return classLoader; } } - if(useAntClassLoader) { + if (useAntClassLoader) { // using AntClassLoader with Closeable so that we can predictably release jar files opened by URLClassLoader AntClassLoader2 classLoader = new AntClassLoader2(parent); classLoader.addPathFiles(paths); @@ -196,9 +198,10 @@ public class ClassicPluginStrategy implements PluginStrategy { // Tom reported that AntClassLoader has a performance issue when Hudson keeps trying to load a class that doesn't exist, // so providing a legacy URLClassLoader support, too List<URL> urls = new ArrayList<URL>(); - for (File path : paths) + for (File path : paths) { urls.add(path.toURI().toURL()); - return new URLClassLoader(urls.toArray(new URL[urls.size()]),parent); + } + return new URLClassLoader(urls.toArray(new URL[urls.size()]), parent); } } @@ -206,6 +209,7 @@ public class ClassicPluginStrategy implements PluginStrategy { * Information about plugins that were originally in the core. */ private static final class DetachedPlugin { + private final String shortName; private final VersionNumber splitWhen; private final String requireVersion; @@ -219,32 +223,34 @@ public class ClassicPluginStrategy implements PluginStrategy { private void fix(Attributes atts, List<PluginWrapper.Dependency> optionalDependencies) { // don't fix the dependency for yourself, or else we'll have a cycle String yourName = atts.getValue("Short-Name"); - if (shortName.equals(yourName)) return; + if (shortName.equals(yourName)) { + return; + } // some earlier versions of maven-hpi-plugin apparently puts "null" as a literal in Hudson-Version. watch out for them. String hudsonVersion = atts.getValue("Hudson-Version"); - if (hudsonVersion == null || hudsonVersion.equals("null") || new VersionNumber(hudsonVersion).compareTo(splitWhen) <= 0) - optionalDependencies.add(new PluginWrapper.Dependency(shortName+':'+requireVersion)); + if (hudsonVersion == null || hudsonVersion.equals("null") || new VersionNumber(hudsonVersion).compareTo(splitWhen) <= 0) { + optionalDependencies.add(new PluginWrapper.Dependency(shortName + ':' + requireVersion)); + } } } - private static final List<DetachedPlugin> DETACHED_LIST = Arrays.asList( - new DetachedPlugin("maven-plugin","1.296","1.296"), - new DetachedPlugin("subversion","1.310","1.0"), - new DetachedPlugin("cvs","1.340","0.1") - ); + new DetachedPlugin("maven-plugin", "1.296", "1.296"), + new DetachedPlugin("subversion", "1.310", "1.0"), + new DetachedPlugin("cvs", "1.340", "0.1")); /** * Computes the classloader that takes the class masking into account. * - * <p> - * This mechanism allows plugins to have their own verions for libraries that core bundles. + * <p> This mechanism allows plugins to have their own verions for libraries + * that core bundles. */ private ClassLoader getBaseClassLoader(Attributes atts) { ClassLoader base = getClass().getClassLoader(); String masked = atts.getValue("Mask-Classes"); - if(masked!=null) + if (masked != null) { base = new MaskingClassLoader(base, masked.trim().split("[ \t\r\n]+")); + } return base; } @@ -254,7 +260,7 @@ public class ClassicPluginStrategy implements PluginStrategy { public <T> List<ExtensionComponent<T>> findComponents(Class<T> type, Hudson hudson) { List<ExtensionFinder> finders; - if (type==ExtensionFinder.class) { + if (type == ExtensionFinder.class) { // Avoid infinite recursion of using ExtensionFinders to find ExtensionFinders finders = Collections.<ExtensionFinder>singletonList(new ExtensionFinder.Sezpoz()); } else { @@ -262,10 +268,12 @@ public class ClassicPluginStrategy implements PluginStrategy { } /** - * See {@link ExtensionFinder#scout(Class, Hudson)} for the dead lock issue and what this does. + * See {@link ExtensionFinder#scout(Class, Hudson)} for the dead lock + * issue and what this does. */ - if (LOGGER.isLoggable(Level.FINER)) - LOGGER.log(Level.FINER,"Scout-loading ExtensionList: "+type, new Throwable()); + if (LOGGER.isLoggable(Level.FINER)) { + LOGGER.log(Level.FINER, "Scout-loading ExtensionList: " + type, new Throwable()); + } for (ExtensionFinder finder : finders) { finder.scout(type, hudson); } @@ -276,8 +284,9 @@ public class ClassicPluginStrategy implements PluginStrategy { r.addAll(finder._find(type, hudson)); } catch (AbstractMethodError e) { // backward compatibility - for (T t : finder.findExtensions(type, hudson)) + for (T t : finder.findExtensions(type, hudson)) { r.add(new ExtensionComponent<T>(t)); + } } } return r; @@ -290,25 +299,25 @@ public class ClassicPluginStrategy implements PluginStrategy { Thread.currentThread().setContextClassLoader(wrapper.classLoader); try { String className = wrapper.getPluginClass(); - if(className==null) { + if (className == null) { // use the default dummy instance wrapper.setPlugin(new DummyImpl()); } else { try { Class clazz = wrapper.classLoader.loadClass(className); Object o = clazz.newInstance(); - if(!(o instanceof Plugin)) { - throw new IOException(className+" doesn't extend from hudson.Plugin"); + if (!(o instanceof Plugin)) { + throw new IOException(className + " doesn't extend from hudson.Plugin"); } wrapper.setPlugin((Plugin) o); } catch (LinkageError e) { - throw new IOException2("Unable to load " + className + " from " + wrapper.getShortName(),e); + throw new IOException2("Unable to load " + className + " from " + wrapper.getShortName(), e); } catch (ClassNotFoundException e) { - throw new IOException2("Unable to load " + className + " from " + wrapper.getShortName(),e); + throw new IOException2("Unable to load " + className + " from " + wrapper.getShortName(), e); } catch (IllegalAccessException e) { - throw new IOException2("Unable to create instance of " + className + " from " + wrapper.getShortName(),e); + throw new IOException2("Unable to create instance of " + className + " from " + wrapper.getShortName(), e); } catch (InstantiationException e) { - throw new IOException2("Unable to create instance of " + className + " from " + wrapper.getShortName(),e); + throw new IOException2("Unable to create instance of " + className + " from " + wrapper.getShortName(), e); } } @@ -317,9 +326,9 @@ public class ClassicPluginStrategy implements PluginStrategy { Plugin plugin = wrapper.getPlugin(); plugin.setServletContext(pluginManager.context); startPlugin(wrapper); - } catch(Throwable t) { + } catch (Throwable t) { // gracefully handle any error in plugin. - throw new IOException2("Failed to initialize",t); + throw new IOException2("Failed to initialize", t); } } finally { Thread.currentThread().setContextClassLoader(old); @@ -332,29 +341,33 @@ public class ClassicPluginStrategy implements PluginStrategy { private static File resolve(File base, String relative) { File rel = new File(relative); - if(rel.isAbsolute()) + if (rel.isAbsolute()) { return rel; - else - return new File(base.getParentFile(),relative); + } else { + return new File(base.getParentFile(), relative); + } } private static void parseClassPath(Manifest manifest, File archive, List<File> paths, String attributeName, String separator) throws IOException { String classPath = manifest.getMainAttributes().getValue(attributeName); - if(classPath==null) return; // attribute not found + if (classPath == null) { + return; // attribute not found + } for (String s : classPath.split(separator)) { File file = resolve(archive, s); - if(file.getName().contains("*")) { + if (file.getName().contains("*")) { // handle wildcard FileSet fs = new FileSet(); File dir = file.getParentFile(); fs.setDir(dir); fs.setIncludes(file.getName()); - for( String included : fs.getDirectoryScanner(new Project()).getIncludedFiles() ) { - paths.add(new File(dir,included)); + for (String included : fs.getDirectoryScanner(new Project()).getIncludedFiles()) { + paths.add(new File(dir, included)); } } else { - if(!file.exists()) - throw new IOException("No such file: "+file); + if (!file.exists()) { + throw new IOException("No such file: " + file); + } paths.add(file); } } @@ -364,14 +377,15 @@ public class ClassicPluginStrategy implements PluginStrategy { * Explodes the plugin into a directory, if necessary. */ private static void explode(File archive, File destDir) throws IOException { - if(!destDir.exists()) + if (!destDir.exists()) { destDir.mkdirs(); + } // timestamp check - File explodeTime = new File(destDir,".timestamp"); - if(explodeTime.exists() && explodeTime.lastModified()==archive.lastModified()) + File explodeTime = new File(destDir, ".timestamp"); + if (explodeTime.exists() && explodeTime.lastModified() == archive.lastModified()) { return; // no need to expand - + } // delete the contents so that old files won't interfere with new files Util.deleteContentsRecursive(destDir); @@ -383,7 +397,7 @@ public class ClassicPluginStrategy implements PluginStrategy { e.setDest(destDir); e.execute(); } catch (BuildException x) { - throw new IOException2("Failed to expand " + archive,x); + throw new IOException2("Failed to expand " + archive, x); } try { @@ -397,11 +411,11 @@ public class ClassicPluginStrategy implements PluginStrategy { * Used to load classes from dependency plugins. */ final class DependencyClassLoader extends ClassLoader { + /** * This classloader is created for this plugin. Useful during debugging. */ private final File _for; - private List<Dependency> dependencies; public DependencyClassLoader(ClassLoader parent, File archive, List<Dependency> dependencies) { @@ -414,12 +428,13 @@ public class ClassicPluginStrategy implements PluginStrategy { protected Class<?> findClass(String name) throws ClassNotFoundException { for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if(p!=null) + if (p != null) { try { return p.classLoader.loadClass(name); } catch (ClassNotFoundException _) { // try next } + } } throw new ClassNotFoundException(name); @@ -430,10 +445,11 @@ public class ClassicPluginStrategy implements PluginStrategy { HashSet<URL> result = new HashSet<URL>(); for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if (p!=null) { + if (p != null) { Enumeration<URL> urls = p.classLoader.getResources(name); - while (urls != null && urls.hasMoreElements()) + while (urls != null && urls.hasMoreElements()) { result.add(urls.nextElement()); + } } } @@ -444,10 +460,11 @@ public class ClassicPluginStrategy implements PluginStrategy { protected URL findResource(String name) { for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if(p!=null) { + if (p != null) { URL url = p.classLoader.getResource(name); - if (url!=null) + if (url != null) { return url; + } } } @@ -456,22 +473,24 @@ public class ClassicPluginStrategy implements PluginStrategy { } /** - * {@link AntClassLoader} with a few methods exposed and {@link Closeable} support. + * {@link AntClassLoader} with a few methods exposed and {@link Closeable} + * support. */ private static final class AntClassLoader2 extends AntClassLoader implements Closeable { + private AntClassLoader2(ClassLoader parent) { - super(parent,true); + super(parent, true); } public void addPathFiles(Collection<File> paths) throws IOException { - for (File f : paths) + for (File f : paths) { addPathFile(f); + } } public void close() throws IOException { cleanup(); } } - - public static boolean useAntClassLoader = Boolean.getBoolean(ClassicPluginStrategy.class.getName()+".useAntClassLoader"); + public static boolean useAntClassLoader = Boolean.getBoolean(ClassicPluginStrategy.class.getName() + ".useAntClassLoader"); } diff --git a/hudson-core/src/main/java/hudson/CloseProofOutputStream.java b/hudson-core/src/main/java/hudson/CloseProofOutputStream.java index 7368885..d616256 100644 --- a/hudson-core/src/main/java/hudson/CloseProofOutputStream.java +++ b/hudson-core/src/main/java/hudson/CloseProofOutputStream.java @@ -7,24 +7,25 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ package hudson; import hudson.util.DelegatingOutputStream; - import java.io.OutputStream; /** * {@link OutputStream} that blocks {@link #close()} method. + * * @author Kohsuke Kawaguchi */ public class CloseProofOutputStream extends DelegatingOutputStream { + public CloseProofOutputStream(OutputStream out) { super(out); } diff --git a/hudson-core/src/main/java/hudson/CopyOnWrite.java b/hudson-core/src/main/java/hudson/CopyOnWrite.java index 4de24ac..3deb8fe 100644 --- a/hudson-core/src/main/java/hudson/CopyOnWrite.java +++ b/hudson-core/src/main/java/hudson/CopyOnWrite.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* + * Contributors: + * * Kohsuke Kawaguchi - * + * * *******************************************************************************/ @@ -23,19 +23,17 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Target; /** - * Represents fields that are protected for concurrency by the copy-on-write semantics. + * Represents fields that are protected for concurrency by the copy-on-write + * semantics. * - * <p> - * Fields marked by this annotation always holds on to an immutable collection. - * A change to the collection must be done by first creating a new collection - * object, making changes, then replacing the reference atomically. + * <p> Fields marked by this annotation always holds on to an immutable + * collection. A change to the collection must be done by first creating a new + * collection object, making changes, then replacing the reference atomically. * - * <p> - * This allows code to access the field without synchronization, and - * greatly reduces the risk of dead-lock bugs. + * <p> This allows code to access the field without synchronization, and greatly + * reduces the risk of dead-lock bugs. * - * <p> - * The field marked with this annotation usually needs to be marked as + * <p> The field marked with this annotation usually needs to be marked as * <tt>volatile</tt>. * * @author Kohsuke Kawaguchi diff --git a/hudson-core/src/main/java/hudson/DNSMultiCast.java b/hudson-core/src/main/java/hudson/DNSMultiCast.java index 31d4bf1..e7a1a97 100644 --- a/hudson-core/src/main/java/hudson/DNSMultiCast.java +++ b/hudson-core/src/main/java/hudson/DNSMultiCast.java @@ -8,7 +8,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * + * * *******************************************************************************/ @@ -31,37 +31,41 @@ import java.util.logging.Logger; * @author Kohsuke Kawaguchi */ public class DNSMultiCast implements Closeable { + private JmDNS jmdns; public DNSMultiCast(Hudson hudson) { - if (disabled) return; // escape hatch - + if (disabled) { + return; // escape hatch + } try { this.jmdns = JmDNS.create(); - Map<String,String> props = new HashMap<String, String>(); + Map<String, String> props = new HashMap<String, String>(); String rootURL = hudson.getRootUrl(); - if (rootURL!=null) + if (rootURL != null) { props.put("url", rootURL); + } try { - props.put("version",String.valueOf(Hudson.getVersion())); + props.put("version", String.valueOf(Hudson.getVersion())); } catch (IllegalArgumentException e) { // failed to parse the version number } TcpSlaveAgentListener tal = hudson.getTcpSlaveAgentListener(); - if (tal!=null) - props.put("slave-port",String.valueOf(tal.getPort())); + if (tal != null) { + props.put("slave-port", String.valueOf(tal.getPort())); + } - jmdns.registerService(ServiceInfo.create("_hudson._tcp.local.","hudson", - 80,0,0,props)); + jmdns.registerService(ServiceInfo.create("_hudson._tcp.local.", "hudson", + 80, 0, 0, props)); } catch (IOException e) { - LOGGER.log(Level.WARNING,"Failed to advertise the service to DNS multi-cast",e); + LOGGER.log(Level.WARNING, "Failed to advertise the service to DNS multi-cast", e); } } public void close() { - if (jmdns!=null) { + if (jmdns != null) { try { jmdns.close(); } catch (IOException ex) { @@ -70,8 +74,6 @@ public class DNSMultiCast implements Closeable { jmdns = null; } } - private static final Logger LOGGER = Logger.getLogger(DNSMultiCast.class.getName()); - - public static boolean disabled = Boolean.getBoolean(DNSMultiCast.class.getName()+".disabled"); + public static boolean disabled = Boolean.getBoolean(DNSMultiCast.class.getName() + ".disabled"); } diff --git a/hudson-core/src/main/java/hudson/DependencyRunner.java b/hudson-core/src/main/java/hudson/DependencyRunner.java index 4875f91..f9270fc 100644 --- a/hudson-core/src/main/java/hudson/DependencyRunner.java +++ b/hudson-core/src/main/java/hudson/DependencyRunner.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi, Winston Prakash, Brian Westrich, Jean-Baptiste Quenot - * + * * *******************************************************************************/ @@ -29,17 +29,13 @@ import java.util.logging.Logger; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; - - /** * Runs a job on all projects in the order of dependencies */ public class DependencyRunner implements Runnable { private static final Logger LOGGER = Logger.getLogger(DependencyRunner.class.getName()); - ProjectRunnable runnable; - List<AbstractProject> polledProjects = new ArrayList<AbstractProject>(); public DependencyRunner(ProjectRunnable runnable) { @@ -54,16 +50,17 @@ public class DependencyRunner implements Runnable { Set<AbstractProject> topLevelProjects = new HashSet<AbstractProject>(); // Get all top-level projects LOGGER.fine("assembling top level projects"); - for (AbstractProject p : Hudson.getInstance().getAllItems(AbstractProject.class)) + for (AbstractProject p : Hudson.getInstance().getAllItems(AbstractProject.class)) { if (p.getUpstreamProjects().size() == 0) { LOGGER.fine("adding top level project " + p.getName()); topLevelProjects.add(p); } else { LOGGER.fine("skipping project since not a top level project: " + p.getName()); } + } populate(topLevelProjects); for (AbstractProject p : polledProjects) { - LOGGER.fine("running project in correct dependency order: " + p.getName()); + LOGGER.fine("running project in correct dependency order: " + p.getName()); runnable.run(p); } } finally { @@ -72,11 +69,11 @@ public class DependencyRunner implements Runnable { } private void populate(Collection<? extends AbstractProject> projectList) { - for (AbstractProject<?,?> p : projectList) { + for (AbstractProject<?, ?> p : projectList) { if (polledProjects.contains(p)) { // Project will be readded at the queue, so that we always use // the longest path - LOGGER.fine("removing project " + p.getName() + " for re-add"); + LOGGER.fine("removing project " + p.getName() + " for re-add"); polledProjects.remove(p); } @@ -89,6 +86,7 @@ public class DependencyRunner implements Runnable { } public interface ProjectRunnable { + void run(AbstractProject p); } } diff --git a/hudson-core/src/main/java/hudson/DescriptorExtensionList.java b/hudson-core/src/main/java/hudson/DescriptorExtensionList.java index a7fdf41..6ad29cd 100644 --- a/hudson-core/src/main/java/hudson/DescriptorExtensionList.java +++ b/hudson-core/src/main/java/hudson/DescriptorExtensionList.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -41,75 +41,75 @@ import org.kohsuke.stapler.Stapler; import net.sf.json.JSONObject; /** - * {@link ExtensionList} for holding a set of {@link Descriptor}s, which is a group of descriptors for - * the same extension point. + * {@link ExtensionList} for holding a set of {@link Descriptor}s, which is a + * group of descriptors for the same extension point. * * Use {@link Hudson#getDescriptorList(Class)} to obtain instances. * - * @param <D> - * Represents the descriptor type. This is {@code Descriptor<T>} normally but often there are subtypes - * of descriptors, like {@link ViewDescriptor}, {@link NodeDescriptor}, etc, and this parameter points - * to those for better type safety of users. + * @param <D> Represents the descriptor type. This is {@code Descriptor<T>} + * normally but often there are subtypes of descriptors, like + * {@link ViewDescriptor}, {@link NodeDescriptor}, etc, and this parameter + * points to those for better type safety of users. * - * The actual value of 'D' is not necessary for the operation of this code, so it's purely for convenience - * of the users of this class. + * The actual value of 'D' is not necessary for the operation of this code, so + * it's purely for convenience of the users of this class. * * @since 1.286 */ public class DescriptorExtensionList<T extends Describable<T>, D extends Descriptor<T>> extends ExtensionList<D> { + /** * Creates a new instance. */ @SuppressWarnings({"unchecked", "rawtypes"}) - public static <T extends Describable<T>,D extends Descriptor<T>> - DescriptorExtensionList<T,D> createDescriptorList(Hudson hudson, Class<T> describableType) { + public static <T extends Describable<T>, D extends Descriptor<T>> DescriptorExtensionList<T, D> createDescriptorList(Hudson hudson, Class<T> describableType) { if (describableType == (Class) Publisher.class) { return (DescriptorExtensionList) new DescriptorExtensionListImpl(hudson); } - return new DescriptorExtensionList<T,D>(hudson,describableType); + return new DescriptorExtensionList<T, D>(hudson, describableType); } - /** * Type of the {@link Describable} that this extension list retains. */ private final Class<T> describableType; protected DescriptorExtensionList(Hudson hudson, Class<T> describableType) { - super(hudson, (Class)Descriptor.class, (CopyOnWriteArrayList)getLegacyDescriptors(describableType)); + super(hudson, (Class) Descriptor.class, (CopyOnWriteArrayList) getLegacyDescriptors(describableType)); this.describableType = describableType; } /** * Finds the descriptor that has the matching fully-qualified class name. * - * @param fqcn - * Fully qualified name of the descriptor, not the describable. + * @param fqcn Fully qualified name of the descriptor, not the describable. */ public D find(String fqcn) { - return Descriptor.find(this,fqcn); + return Descriptor.find(this, fqcn); } /** - * Finds the descriptor that describes the given type. - * That is, if this method returns d, {@code d.clazz==type} + * Finds the descriptor that describes the given type. That is, if this + * method returns d, {@code d.clazz==type} */ public D find(Class<? extends T> type) { - for (D d : this) - if (d.clazz==type) + for (D d : this) { + if (d.clazz == type) { return d; + } + } return null; } /** - * Creates a new instance of a {@link Describable} - * from the structured form submission data posted - * by a radio button group. + * Creates a new instance of a {@link Describable} from the structured form + * submission data posted by a radio button group. */ public T newInstanceFromRadioList(JSONObject config) throws FormException { - if(config.isNullObject()) + if (config.isNullObject()) { return null; // none was selected + } int idx = config.getInt("value"); - return get(idx).newInstance(Stapler.getCurrentRequest(),config); + return get(idx).newInstance(Stapler.getCurrentRequest(), config); } public T newInstanceFromRadioList(JSONObject parent, String name) throws FormException { @@ -122,14 +122,17 @@ public class DescriptorExtensionList<T extends Describable<T>, D extends Descrip * If none is found, null is returned. */ public Descriptor<T> findByName(String id) { - for (Descriptor<T> d : this) - if(d.getId().equals(id)) + for (Descriptor<T> d : this) { + if (d.getId().equals(id)) { return d; + } + } return null; } /** - * {@link #load()} in the descriptor is not a real load activity, so locking against "this" is enough. + * {@link #load()} in the descriptor is not a real load activity, so locking + * against "this" is enough. */ @Override protected Object getLoadLock() { @@ -137,35 +140,37 @@ public class DescriptorExtensionList<T extends Describable<T>, D extends Descrip } /** - * Loading the descriptors in this case means filtering the descriptor from the master {@link ExtensionList}. + * Loading the descriptors in this case means filtering the descriptor from + * the master {@link ExtensionList}. */ @Override protected List<ExtensionComponent<D>> load() { List<ExtensionComponent<D>> r = new ArrayList<ExtensionComponent<D>>(); - for( ExtensionComponent<Descriptor> c : hudson.getExtensionList(Descriptor.class).getComponents() ) { + for (ExtensionComponent<Descriptor> c : hudson.getExtensionList(Descriptor.class).getComponents()) { Descriptor d = c.getInstance(); Type subTyping = Types.getBaseClass(d.getClass(), Descriptor.class); if (!(subTyping instanceof ParameterizedType)) { - LOGGER.severe(d.getClass()+" doesn't extend Descriptor with a type parameter"); + LOGGER.severe(d.getClass() + " doesn't extend Descriptor with a type parameter"); continue; // skip this one } - if(Types.erasure(Types.getTypeArgument(subTyping,0))==(Class)describableType) - r.add((ExtensionComponent)c); + if (Types.erasure(Types.getTypeArgument(subTyping, 0)) == (Class) describableType) { + r.add((ExtensionComponent) c); + } } return r; } - /** - * Stores manually registered Descriptor instances. Keyed by the {@link Describable} type. + * Stores manually registered Descriptor instances. Keyed by the + * {@link Describable} type. */ - private static final Memoizer<Class,CopyOnWriteArrayList<ExtensionComponent<Descriptor>>> legacyDescriptors = new Memoizer<Class,CopyOnWriteArrayList<ExtensionComponent<Descriptor>>>() { + private static final Memoizer<Class, CopyOnWriteArrayList<ExtensionComponent<Descriptor>>> legacyDescriptors = new Memoizer<Class, CopyOnWriteArrayList<ExtensionComponent<Descriptor>>>() { public CopyOnWriteArrayList compute(Class key) { return new CopyOnWriteArrayList(); } }; private static <T extends Describable<T>> CopyOnWriteArrayList<ExtensionComponent<Descriptor<T>>> getLegacyDescriptors(Class<T> type) { - return (CopyOnWriteArrayList)legacyDescriptors.get(type); + return (CopyOnWriteArrayList) legacyDescriptors.get(type); } /** @@ -174,13 +179,12 @@ public class DescriptorExtensionList<T extends Describable<T>, D extends Descrip public static Iterable<Descriptor> listLegacyInstances() { return new Iterable<Descriptor>() { public Iterator<Descriptor> iterator() { - return new AdaptedIterator<ExtensionComponent<Descriptor>,Descriptor>( - new FlattenIterator<ExtensionComponent<Descriptor>,CopyOnWriteArrayList<ExtensionComponent<Descriptor>>>(legacyDescriptors.values()) { - protected Iterator<ExtensionComponent<Descriptor>> expand(CopyOnWriteArrayList<ExtensionComponent<Descriptor>> v) { - return v.iterator(); - } - }) { - + return new AdaptedIterator<ExtensionComponent<Descriptor>, Descriptor>( + new FlattenIterator<ExtensionComponent<Descriptor>, CopyOnWriteArrayList<ExtensionComponent<Descriptor>>>(legacyDescriptors.values()) { + protected Iterator<ExtensionComponent<Descriptor>> expand(CopyOnWriteArrayList<ExtensionComponent<Descriptor>> v) { + return v.iterator(); + } + }) { protected Descriptor adapt(ExtensionComponent<Descriptor> item) { return item.getInstance(); } @@ -195,6 +199,5 @@ public class DescriptorExtensionList<T extends Describable<T>, D extends Descrip public static void clearLegacyInstances() { legacyDescriptors.clear(); } - private static final Logger LOGGER = Logger.getLogger(DescriptorExtensionList.class.getName()); } diff --git a/hudson-core/src/main/java/hudson/EnvVars.java b/hudson-core/src/main/java/hudson/EnvVars.java index 8b2fb37..4200b88 100644 --- a/hudson-core/src/main/java/hudson/EnvVars.java +++ b/hudson-core/src/main/java/hudson/EnvVars.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, Red Hat, Inc. - * + * Contributors: + * + * Kohsuke Kawaguchi, Red Hat, Inc. + * * *******************************************************************************/ @@ -31,44 +31,44 @@ import org.apache.commons.lang3.StringUtils; /** * Environment variables. * - * <p> - * While all the platforms I tested (Linux 2.6, Solaris, and Windows XP) have the case sensitive - * environment variable table, Windows batch script handles environment variable in the case preserving - * but case <b>insensitive</b> way (that is, cmd.exe can get both FOO and foo as environment variables - * when it's launched, and the "set" command will display it accordingly, but "echo %foo%" results in - * echoing the value of "FOO", not "foo" — this is presumably caused by the behavior of the underlying - * Win32 API <tt>GetEnvironmentVariable</tt> acting in case insensitive way.) Windows users are also - * used to write environment variable case-insensitively (like %Path% vs %PATH%), and you can see many - * documents on the web that claims Windows environment variables are case insensitive. + * <p> While all the platforms I tested (Linux 2.6, Solaris, and Windows XP) + * have the case sensitive environment variable table, Windows batch script + * handles environment variable in the case preserving but case + * <b>insensitive</b> way (that is, cmd.exe can get both FOO and foo as + * environment variables when it's launched, and the "set" command will display + * it accordingly, but "echo %foo%" results in echoing the value of "FOO", not + * "foo" — this is presumably caused by the behavior of the underlying + * Win32 API <tt>GetEnvironmentVariable</tt> acting in case insensitive way.) + * Windows users are also used to write environment variable case-insensitively + * (like %Path% vs %PATH%), and you can see many documents on the web that + * claims Windows environment variables are case insensitive. * - * <p> - * So for a consistent cross platform behavior, it creates the least confusion to make the table - * case insensitive but case preserving. + * <p> So for a consistent cross platform behavior, it creates the least + * confusion to make the table case insensitive but case preserving. * - * <p> - * In Hudson, often we need to build up "environment variable overrides" - * on master, then to execute the process on slaves. This causes a problem - * when working with variables like <tt>PATH</tt>. So to make this work, - * we introduce a special convention <tt>PATH+FOO</tt> — all entries - * that starts with <tt>PATH+</tt> are merged and prepended to the inherited - * <tt>PATH</tt> variable, on the process where a new process is executed. + * <p> In Hudson, often we need to build up "environment variable overrides" on + * master, then to execute the process on slaves. This causes a problem when + * working with variables like <tt>PATH</tt>. So to make this work, we introduce + * a special convention <tt>PATH+FOO</tt> — all entries that starts with + * <tt>PATH+</tt> are merged and prepended to the inherited <tt>PATH</tt> + * variable, on the process where a new process is executed. * * @author Kohsuke Kawaguchi */ -public class EnvVars extends TreeMap<String,String> { +public class EnvVars extends TreeMap<String, String> { + /** - * Environment property which will be exposed. Value - name of currently logged user. + * Environment property which will be exposed. Value - name of currently + * logged user. */ public static final String HUDSON_USER_ENV_KEY = "HUDSON_USER"; - /** - * If this {@link EnvVars} object represents the whole environment variable set, - * not just a partial list used for overriding later, then we need to know - * the platform for which this env vars are targeted for, or else we won't konw - * how to merge variables properly. + * If this {@link EnvVars} object represents the whole environment variable + * set, not just a partial list used for overriding later, then we need to + * know the platform for which this env vars are targeted for, or else we + * won't konw how to merge variables properly. * - * <p> - * So this property remembers that information. + * <p> So this property remembers that information. */ private Platform platform; @@ -76,7 +76,7 @@ public class EnvVars extends TreeMap<String,String> { super(CaseInsensitiveComparator.INSTANCE); } - public EnvVars(Map<String,String> m) { + public EnvVars(Map<String, String> m) { this(); putAll(m); @@ -90,59 +90,63 @@ public class EnvVars extends TreeMap<String,String> { public EnvVars(EnvVars m) { // this constructor is so that in future we can get rid of the downcasting. - this((Map)m); + this((Map) m); } /** - * Builds an environment variables from an array of the form <tt>"key","value","key","value"...</tt> + * Builds an environment variables from an array of the form + * <tt>"key","value","key","value"...</tt> */ public EnvVars(String... keyValuePairs) { this(); - if(keyValuePairs.length%2!=0) + if (keyValuePairs.length % 2 != 0) { throw new IllegalArgumentException(Arrays.asList(keyValuePairs).toString()); - for( int i=0; i<keyValuePairs.length; i+=2 ) - put(keyValuePairs[i],keyValuePairs[i+1]); + } + for (int i = 0; i < keyValuePairs.length; i += 2) { + put(keyValuePairs[i], keyValuePairs[i + 1]); + } } /** * Overrides the current entry by the given entry. * - * <p> - * Handles <tt>PATH+XYZ</tt> notation. + * <p> Handles <tt>PATH+XYZ</tt> notation. */ public void override(String key, String value) { - if(value==null || value.length()==0) { + if (value == null || value.length() == 0) { remove(key); return; } int idx = key.indexOf('+'); - if(idx>0) { - String realKey = key.substring(0,idx); + if (idx > 0) { + String realKey = key.substring(0, idx); String v = get(realKey); - if(v==null) v=value; - else { + if (v == null) { + v = value; + } else { // we might be handling environment variables for a slave that can have different path separator // than the master, so the following is an attempt to get it right. // it's still more error prone that I'd like. - char ch = platform==null ? File.pathSeparatorChar : platform.pathSeparator; - v=value+ch+v; + char ch = platform == null ? File.pathSeparatorChar : platform.pathSeparator; + v = value + ch + v; } - put(realKey,v); + put(realKey, v); return; } - put(key,value); + put(key, value); } /** - * Overrides all values in the map by the given map. - * See {@link #override(String, String)}. + * Overrides all values in the map by the given map. See + * {@link #override(String, String)}. + * * @return this */ - public EnvVars overrideAll(Map<String,String> all) { + public EnvVars overrideAll(Map<String, String> all) { for (Map.Entry<String, String> e : all.entrySet()) { - override(e.getKey(),e.getValue()); + override(e.getKey(), e.getValue()); } return this; } @@ -150,30 +154,33 @@ public class EnvVars extends TreeMap<String,String> { /** * Resolves environment variables against each other. */ - public static void resolve(Map<String, String> env) { - for (Map.Entry<String,String> entry: env.entrySet()) { - entry.setValue(Util.replaceMacro(entry.getValue(), env)); - } - } + public static void resolve(Map<String, String> env) { + for (Map.Entry<String, String> entry : env.entrySet()) { + entry.setValue(Util.replaceMacro(entry.getValue(), env)); + } + } @Override public String put(String key, String value) { - if (value==null) throw new IllegalArgumentException("Null value not allowed as an environment variable: "+key); - return super.put(key,value); + if (value == null) { + throw new IllegalArgumentException("Null value not allowed as an environment variable: " + key); + } + return super.put(key, value); } - + /** * Takes a string that looks like "a=b" and adds that to this map. */ public void addLine(String line) { int sep = line.indexOf('='); - if(sep > 0) { - put(line.substring(0,sep),line.substring(sep+1)); + if (sep > 0) { + put(line.substring(0, sep), line.substring(sep + 1)); } } /** - * Expands the variables in the given string by using environment variables represented in 'this'. + * Expands the variables in the given string by using environment variables + * represented in 'this'. */ public String expand(String s) { return Util.replaceMacro(s, this); @@ -217,46 +224,45 @@ public class EnvVars extends TreeMap<String,String> { /** * Obtains the environment variables of a remote peer. * - * @param channel - * Can be null, in which case the map indicating "N/A" will be returned. - * @return - * A fresh copy that can be owned and modified by the caller. + * @param channel Can be null, in which case the map indicating "N/A" will + * be returned. + * @return A fresh copy that can be owned and modified by the caller. */ public static EnvVars getRemote(VirtualChannel channel) throws IOException, InterruptedException { - if(channel==null) - return new EnvVars("N/A","N/A"); + if (channel == null) { + return new EnvVars("N/A", "N/A"); + } return channel.call(new GetEnvVars()); } - private static final class GetEnvVars implements Callable<EnvVars,RuntimeException> { + private static final class GetEnvVars implements Callable<EnvVars, RuntimeException> { + public EnvVars call() { return new EnvVars(EnvVars.masterEnvVars); } private static final long serialVersionUID = 1L; } - /** * Environmental variables that we've inherited. * - * <p> - * Despite what the name might imply, this is the environment variable - * of the current JVM process. And therefore, it is Hudson master's environment - * variables only when you access this from the master. + * <p> Despite what the name might imply, this is the environment variable + * of the current JVM process. And therefore, it is Hudson master's + * environment variables only when you access this from the master. * - * <p> - * If you access this field from slaves, then this is the environment + * <p> If you access this field from slaves, then this is the environment * variable of the slave agent. */ - public static final Map<String,String> masterEnvVars = initMaster(); + public static final Map<String, String> masterEnvVars = initMaster(); private static EnvVars initMaster() { EnvVars vars = new EnvVars(System.getenv()); vars.platform = Platform.current(); - if(Main.isUnitTest || Main.isDevelopmentMode) - // if unit test is launched with maven debug switch, - // we need to prevent forked Maven processes from seeing it, or else - // they'll hang + if (Main.isUnitTest || Main.isDevelopmentMode) // if unit test is launched with maven debug switch, + // we need to prevent forked Maven processes from seeing it, or else + // they'll hang + { vars.remove("MAVEN_OPTS"); + } return vars; } } diff --git a/hudson-core/src/main/java/hudson/Extension.java b/hudson-core/src/main/java/hudson/Extension.java index 6e7bd47..fee3524 100644 --- a/hudson-core/src/main/java/hudson/Extension.java +++ b/hudson-core/src/main/java/hudson/Extension.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -26,30 +26,26 @@ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * Marks a field, a method, or a class for automatic discovery, so that Hudson can locate - * implementations of {@link ExtensionPoint}s automatically. + * Marks a field, a method, or a class for automatic discovery, so that Hudson + * can locate implementations of {@link ExtensionPoint}s automatically. * - * <p> - * (In contrast, in earlier Hudson, the registration was manual.) + * <p> (In contrast, in earlier Hudson, the registration was manual.) * - * <p> - * In a simplest case, put this on your class, and Hudson will create an instance of it - * and register it to the appropriate {@link ExtensionList}. + * <p> In a simplest case, put this on your class, and Hudson will create an + * instance of it and register it to the appropriate {@link ExtensionList}. * - * <p> - * If you'd like Hudson to call - * a factory method instead of a constructor, put this annotation on your static factory - * method. Hudson will invoke it and if the method returns a non-null instance, it'll be - * registered. The return type of the method is used to determine which {@link ExtensionList} - * will get the instance. + * <p> If you'd like Hudson to call a factory method instead of a constructor, + * put this annotation on your static factory method. Hudson will invoke it and + * if the method returns a non-null instance, it'll be registered. The return + * type of the method is used to determine which {@link ExtensionList} will get + * the instance. * - * Finally, you can put this annotation on a static field if the field contains a reference - * to an instance that you'd like to register. + * Finally, you can put this annotation on a static field if the field contains + * a reference to an instance that you'd like to register. * - * <p> - * This is the default way of having your implementations auto-registered to Hudson, - * but Hudson also supports arbitrary DI containers for hosting your implementations. - * See {@link ExtensionFinder} for more details. + * <p> This is the default way of having your implementations auto-registered to + * Hudson, but Hudson also supports arbitrary DI containers for hosting your + * implementations. See {@link ExtensionFinder} for more details. * * @author Kohsuke Kawaguchi * @since 1.286 @@ -62,18 +58,22 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({TYPE, FIELD, METHOD}) @Documented public @interface Extension { + /** * Used for sorting extensions. * - * Extensions will be sorted in the descending order of the ordinal. - * This is a rather poor approach to the problem, so its use is generally discouraged. + * Extensions will be sorted in the descending order of the ordinal. This is + * a rather poor approach to the problem, so its use is generally + * discouraged. * * @since 1.306 */ double ordinal() default 0; /** - * If an extension is optional, don't log any class loading errors when reading it. + * If an extension is optional, don't log any class loading errors when + * reading it. + * * @since 1.358 */ boolean optional() default false; diff --git a/hudson-core/src/main/java/hudson/ExtensionComponent.java b/hudson-core/src/main/java/hudson/ExtensionComponent.java index 2e42ebe..b0f2cb1 100644 --- a/hudson-core/src/main/java/hudson/ExtensionComponent.java +++ b/hudson-core/src/main/java/hudson/ExtensionComponent.java @@ -7,9 +7,9 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * * - * * Kohsuke Kawaguchi * *******************************************************************************/ @@ -17,13 +17,14 @@ package hudson; /** - * Discovered {@link Extension} object with a bit of metadata for Hudson. - * This is a plain value object. + * Discovered {@link Extension} object with a bit of metadata for Hudson. This + * is a plain value object. * * @author Kohsuke Kawaguchi * @since 1.356 */ public class ExtensionComponent<T> implements Comparable<ExtensionComponent<T>> { + private final T instance; private final double ordinal; @@ -33,11 +34,11 @@ public class ExtensionComponent<T> implements Comparable<ExtensionComponent<T>> } public ExtensionComponent(T instance, Extension annotation) { - this(instance,annotation.ordinal()); + this(instance, annotation.ordinal()); } public ExtensionComponent(T instance) { - this(instance,0); + this(instance, 0); } /** @@ -57,13 +58,18 @@ public class ExtensionComponent<T> implements Comparable<ExtensionComponent<T>> } /** - * Sort {@link ExtensionComponent}s in the descending order of {@link #ordinal()}. + * Sort {@link ExtensionComponent}s in the descending order of + * {@link #ordinal()}. */ public int compareTo(ExtensionComponent<T> that) { double a = this.ordinal(); double b = that.ordinal(); - if (a>b) return -1; - if (a<b) return 1; + if (a > b) { + return -1; + } + if (a < b) { + return 1; + } return 0; } } diff --git a/hudson-core/src/main/java/hudson/ExtensionFinder.java b/hudson-core/src/main/java/hudson/ExtensionFinder.java index e756cc2..de11396 100644 --- a/hudson-core/src/main/java/hudson/ExtensionFinder.java +++ b/hudson-core/src/main/java/hudson/ExtensionFinder.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * InfraDNA, Inc. - * + * * *******************************************************************************/ @@ -36,21 +36,22 @@ import java.lang.reflect.Method; /** * Discovers the implementations of an extension point. * - * <p> - * This extension point allows you to write your implementations of {@link ExtensionPoint}s - * in arbitrary DI containers, and have Hudson discover them. + * <p> This extension point allows you to write your implementations of + * {@link ExtensionPoint}s in arbitrary DI containers, and have Hudson discover + * them. * - * <p> - * {@link ExtensionFinder} itself is an extension point, but to avoid infinite recursion, - * Hudson discovers {@link ExtensionFinder}s through {@link Sezpoz} and that alone. + * <p> {@link ExtensionFinder} itself is an extension point, but to avoid + * infinite recursion, Hudson discovers {@link ExtensionFinder}s through + * {@link Sezpoz} and that alone. * * @author Kohsuke Kawaguchi * @since 1.286 */ public abstract class ExtensionFinder implements ExtensionPoint { + /** - * @deprecated as of 1.356 - * Use and implement {@link #find(Class, Hudson)} that allows us to put some metadata. + * @deprecated as of 1.356 Use and implement {@link #find(Class, Hudson)} + * that allows us to put some metadata. */ @Deprecated public <T> Collection<T> findExtensions(Class<T> type, Hudson hudson) { @@ -60,60 +61,57 @@ public abstract class ExtensionFinder implements ExtensionPoint { /** * Discover extensions of the given type. * - * <p> - * This method is called only once per the given type after all the plugins are loaded, - * so implementations need not worry about caching. + * <p> This method is called only once per the given type after all the + * plugins are loaded, so implementations need not worry about caching. * - * @param <T> - * The type of the extension points. This is not bound to {@link ExtensionPoint} because - * of {@link Descriptor}, which by itself doesn't implement {@link ExtensionPoint} for - * a historical reason. - * @param hudson - * Hudson whose behalf this extension finder is performing lookup. - * @return - * Can be empty but never null. - * @since 1.356 - * Older implementations provide {@link #findExtensions(Class, Hudson)} + * @param <T> The type of the extension points. This is not bound to + * {@link ExtensionPoint} because of {@link Descriptor}, which by itself + * doesn't implement {@link ExtensionPoint} for a historical reason. + * @param hudson Hudson whose behalf this extension finder is performing + * lookup. + * @return Can be empty but never null. + * @since 1.356 Older implementations provide + * {@link #findExtensions(Class, Hudson)} */ public abstract <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson); /** - * A pointless function to work around what appears to be a HotSpot problem. See HUDSON-5756 and bug 6933067 - * on BugParade for more details. + * A pointless function to work around what appears to be a HotSpot problem. + * See HUDSON-5756 and bug 6933067 on BugParade for more details. */ public <T> Collection<ExtensionComponent<T>> _find(Class<T> type, Hudson hudson) { - return find(type,hudson); + return find(type, hudson); } /** - * Performs class initializations without creating instances. + * Performs class initializations without creating instances. * - * If two threads try to initialize classes in the opposite order, a dead lock will ensue, - * and we can get into a similar situation with {@link ExtensionFinder}s. + * If two threads try to initialize classes in the opposite order, a dead + * lock will ensue, and we can get into a similar situation with + * {@link ExtensionFinder}s. * - * <p> - * That is, one thread can try to list extensions, which results in {@link ExtensionFinder} - * loading and initializing classes. This happens inside a context of a lock, so that - * another thread that tries to list the same extensions don't end up creating different - * extension instances. So this activity locks extension list first, then class initialization next. + * <p> That is, one thread can try to list extensions, which results in + * {@link ExtensionFinder} loading and initializing classes. This happens + * inside a context of a lock, so that another thread that tries to list the + * same extensions don't end up creating different extension instances. So + * this activity locks extension list first, then class initialization next. * - * <p> - * In the mean time, another thread can load and initialize a class, and that initialization - * can eventually results in listing up extensions, for example through static initializer. - * Such activity locks class initialization first, then locks extension list. + * <p> In the mean time, another thread can load and initialize a class, and + * that initialization can eventually results in listing up extensions, for + * example through static initializer. Such activity locks class + * initialization first, then locks extension list. * - * <p> - * This inconsistent locking order results in a dead lock, you see. + * <p> This inconsistent locking order results in a dead lock, you see. * - * <p> - * So to reduce the likelihood, this method is called in prior to {@link #find(Class, Hudson)} invocation, - * but from outside the lock. The implementation is expected to perform all the class initialization activities - * from here. + * <p> So to reduce the likelihood, this method is called in prior to + * {@link #find(Class, Hudson)} invocation, but from outside the lock. The + * implementation is expected to perform all the class initialization + * activities from here. * - * <p> - * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208 for how to force a class initialization. - * Also see http://kohsuke.org/2010/09/01/deadlock-that-you-cant-avoid/ for how class initialization - * can results in a dead lock. + * <p> See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208 for + * how to force a class initialization. Also see + * http://kohsuke.org/2010/09/01/deadlock-that-you-cant-avoid/ for how class + * initialization can results in a dead lock. */ public void scout(Class extensionType, Hudson hudson) { } @@ -121,28 +119,28 @@ public abstract class ExtensionFinder implements ExtensionPoint { /** * The default implementation that looks for the {@link Extension} marker. * - * <p> - * Uses Sezpoz as the underlying mechanism. + * <p> Uses Sezpoz as the underlying mechanism. */ @Extension public static final class Sezpoz extends ExtensionFinder { - private volatile List<IndexItem<Extension,Object>> indices; + private volatile List<IndexItem<Extension, Object>> indices; /** - * Loads indices (ideally once but as few times as possible), then reuse them later. - * {@link ExtensionList#ensureLoaded()} guarantees that this method won't be called until - * {@link InitMilestone#PLUGINS_PREPARED} is attained, so this method is guaranteed to - * see all the classes and indices. + * Loads indices (ideally once but as few times as possible), then reuse + * them later. {@link ExtensionList#ensureLoaded()} guarantees that this + * method won't be called until {@link InitMilestone#PLUGINS_PREPARED} + * is attained, so this method is guaranteed to see all the classes and + * indices. */ - private List<IndexItem<Extension,Object>> getIndices() { + private List<IndexItem<Extension, Object>> getIndices() { // this method cannot be synchronized because of a dead lock possibility in the following order of events: // 1. thread X can start listing indices, locking this object 'SZ' // 2. thread Y starts loading a class, locking a classloader 'CL' // 3. thread X needs to load a class, now blocked on CL // 4. thread Y decides to load extensions, now blocked on SZ. // 5. dead lock - if (indices==null) { + if (indices == null) { ClassLoader cl = Hudson.getInstance().getPluginManager().uberClassLoader; indices = ImmutableList.copyOf(Index.load(Extension.class, Object.class, cl)); } @@ -152,34 +150,34 @@ public abstract class ExtensionFinder implements ExtensionPoint { public <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson) { List<ExtensionComponent<T>> result = new ArrayList<ExtensionComponent<T>>(); - for (IndexItem<Extension,Object> item : getIndices()) { + for (IndexItem<Extension, Object> item : getIndices()) { try { AnnotatedElement e = item.element(); Class<?> extType; if (e instanceof Class) { extType = (Class) e; - } else - if (e instanceof Field) { - extType = ((Field)e).getType(); - } else - if (e instanceof Method) { - extType = ((Method)e).getReturnType(); - } else + } else if (e instanceof Field) { + extType = ((Field) e).getType(); + } else if (e instanceof Method) { + extType = ((Method) e).getReturnType(); + } else { throw new AssertionError(); + } - if(type.isAssignableFrom(extType)) { + if (type.isAssignableFrom(extType)) { Object instance = item.instance(); - if(instance!=null) - result.add(new ExtensionComponent<T>(type.cast(instance),item.annotation())); + if (instance != null) { + result.add(new ExtensionComponent<T>(type.cast(instance), item.annotation())); + } } } catch (LinkageError e) { // sometimes the instantiation fails in an indirect classloading failure, // which results in a LinkageError LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING, - "Failed to load "+item.className(), e); + "Failed to load " + item.className(), e); } catch (InstantiationException e) { LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING, - "Failed to load "+item.className(), e); + "Failed to load " + item.className(), e); } } @@ -188,7 +186,7 @@ public abstract class ExtensionFinder implements ExtensionPoint { @Override public void scout(Class extensionType, Hudson hudson) { - for (IndexItem<Extension,Object> item : getIndices()) { + for (IndexItem<Extension, Object> item : getIndices()) { try { // we might end up having multiple threads concurrently calling into element(), // but we can't synchronize this --- if we do, the one thread that's supposed to load a class @@ -198,28 +196,26 @@ public abstract class ExtensionFinder implements ExtensionPoint { Class<?> extType; if (e instanceof Class) { extType = (Class) e; - } else - if (e instanceof Field) { - extType = ((Field)e).getType(); - } else - if (e instanceof Method) { - extType = ((Method)e).getReturnType(); - } else + } else if (e instanceof Field) { + extType = ((Field) e).getType(); + } else if (e instanceof Method) { + extType = ((Method) e).getReturnType(); + } else { throw new AssertionError(); + } // according to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208 // this appears to be the only way to force a class initialization - Class.forName(extType.getName(),true,extType.getClassLoader()); + Class.forName(extType.getName(), true, extType.getClassLoader()); } catch (InstantiationException e) { LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING, - "Failed to scout "+item.className(), e); + "Failed to scout " + item.className(), e); } catch (ClassNotFoundException e) { - LOGGER.log(Level.WARNING,"Failed to scout "+item.className(), e); + LOGGER.log(Level.WARNING, "Failed to scout " + item.className(), e); } catch (LinkageError e) { - LOGGER.log(Level.WARNING,"Failed to scout "+item.className(), e); + LOGGER.log(Level.WARNING, "Failed to scout " + item.className(), e); } } } } - private static final Logger LOGGER = Logger.getLogger(ExtensionFinder.class.getName()); } diff --git a/hudson-core/src/main/java/hudson/ExtensionList.java b/hudson-core/src/main/java/hudson/ExtensionList.java index 53a5ee7..f47304e 100644 --- a/hudson-core/src/main/java/hudson/ExtensionList.java +++ b/hudson-core/src/main/java/hudson/ExtensionList.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -38,18 +38,18 @@ import java.util.logging.Logger; /** * Retains the known extension instances for the given type 'T'. * - * <p> - * Extensions are loaded lazily on demand and automatically by using {@link ExtensionFinder}, but this - * class also provides a mechanism to provide compatibility with the older {@link DescriptorList}-based - * manual registration, + * <p> Extensions are loaded lazily on demand and automatically by using + * {@link ExtensionFinder}, but this class also provides a mechanism to provide + * compatibility with the older {@link DescriptorList}-based manual + * registration, * - * <p> - * All {@link ExtensionList} instances should be owned by {@link Hudson}, even though - * extension points can be defined by anyone on any type. Use {@link Hudson#getExtensionList(Class)} - * and {@link Hudson#getDescriptorList(Class)} to obtain the instances. + * <p> All {@link ExtensionList} instances should be owned by {@link Hudson}, + * even though extension points can be defined by anyone on any type. Use + * {@link Hudson#getExtensionList(Class)} and + * {@link Hudson#getDescriptorList(Class)} to obtain the instances. * - * @param <T> - * Type of the extension point. This class holds instances of the subtypes of 'T'. + * @param <T> Type of the extension point. This class holds instances of the + * subtypes of 'T'. * * @author Kohsuke Kawaguchi * @since 1.286 @@ -58,31 +58,32 @@ import java.util.logging.Logger; */ public class ExtensionList<T> extends AbstractList<T> { //TODO: review and check whether we can do it private + public final Hudson hudson; public final Class<T> extensionType; - /** * Once discovered, extensions are retained here. */ @CopyOnWrite private volatile List<ExtensionComponent<T>> extensions; - /** * Place to store manually registered instances with the per-Hudson scope. - * {@link CopyOnWriteArrayList} is used here to support concurrent iterations and mutation. + * {@link CopyOnWriteArrayList} is used here to support concurrent + * iterations and mutation. */ private final CopyOnWriteArrayList<ExtensionComponent<T>> legacyInstances; protected ExtensionList(Hudson hudson, Class<T> extensionType) { - this(hudson,extensionType,new CopyOnWriteArrayList<ExtensionComponent<T>>()); + this(hudson, extensionType, new CopyOnWriteArrayList<ExtensionComponent<T>>()); } /** * - * @param legacyStore - * Place to store manually registered instances. The version of the constructor that - * omits this uses a new {@link Vector}, making the storage lifespan tied to the life of {@link ExtensionList}. - * If the manually registered instances are scoped to VM level, the caller should pass in a static list. + * @param legacyStore Place to store manually registered instances. The + * version of the constructor that omits this uses a new {@link Vector}, + * making the storage lifespan tied to the life of {@link ExtensionList}. If + * the manually registered instances are scoped to VM level, the caller + * should pass in a static list. */ protected ExtensionList(Hudson hudson, Class<T> extensionType, CopyOnWriteArrayList<ExtensionComponent<T>> legacyStore) { this.hudson = hudson; @@ -95,16 +96,18 @@ public class ExtensionList<T> extends AbstractList<T> { * or return null. */ public <U extends T> U get(Class<U> type) { - for (T ext : this) - if(ext.getClass()==type) + for (T ext : this) { + if (ext.getClass() == type) { return type.cast(ext); + } + } return null; } @Override public Iterator<T> iterator() { // we need to intercept mutation, so for now don't allow Iterator.remove - return new AdaptedIterator<ExtensionComponent<T>,T>(Iterators.readOnly(ensureLoaded().iterator())) { + return new AdaptedIterator<ExtensionComponent<T>, T>(Iterators.readOnly(ensureLoaded().iterator())) { protected T adapt(ExtensionComponent<T> item) { return item.getInstance(); } @@ -112,7 +115,8 @@ public class ExtensionList<T> extends AbstractList<T> { } /** - * Gets the same thing as the 'this' list represents, except as {@link ExtensionComponent}s. + * Gets the same thing as the 'this' list represents, except as + * {@link ExtensionComponent}s. */ public List<ExtensionComponent<T>> getComponents() { return Collections.unmodifiableList(ensureLoaded()); @@ -128,10 +132,10 @@ public class ExtensionList<T> extends AbstractList<T> { @Override public synchronized boolean remove(Object o) { - removeComponent(legacyInstances,o); - if(extensions!=null) { + removeComponent(legacyInstances, o); + if (extensions != null) { List<ExtensionComponent<T>> r = new ArrayList<ExtensionComponent<T>>(extensions); - removeComponent(r,o); + removeComponent(r, o); extensions = sort(r); } return true; @@ -139,7 +143,7 @@ public class ExtensionList<T> extends AbstractList<T> { private <T> void removeComponent(Collection<ExtensionComponent<T>> collection, Object t) { for (Iterator<ExtensionComponent<T>> itr = collection.iterator(); itr.hasNext();) { - ExtensionComponent<T> c = itr.next(); + ExtensionComponent<T> c = itr.next(); if (c.getInstance().equals(t)) { collection.remove(c); return; @@ -157,14 +161,13 @@ public class ExtensionList<T> extends AbstractList<T> { /** * Write access will put the instance into a legacy store. * - * @deprecated since 2009-02-23. - * Prefer automatic registration. + * @deprecated since 2009-02-23. Prefer automatic registration. */ @Override public synchronized boolean add(T t) { legacyInstances.add(new ExtensionComponent<T>(t)); // if we've already filled extensions, add it - if(extensions!=null) { + if (extensions != null) { List<ExtensionComponent<T>> r = new ArrayList<ExtensionComponent<T>>(extensions); r.add(new ExtensionComponent<T>(t)); extensions = sort(r); @@ -183,9 +186,11 @@ public class ExtensionList<T> extends AbstractList<T> { * @since 1.349 */ public T getDynamic(String className) { - for (T t : this) - if (t.getClass().getName().equals(className)) + for (T t : this) { + if (t.getClass().getName().equals(className)) { return t; + } + } return null; } @@ -198,13 +203,14 @@ public class ExtensionList<T> extends AbstractList<T> { } private List<ExtensionComponent<T>> ensureLoaded() { - if(extensions!=null) + if (extensions != null) { return extensions; // already loaded - if(Hudson.getInstance().getInitLevel().compareTo(InitMilestone.PLUGINS_PREPARED)<0) + } + if (Hudson.getInstance().getInitLevel().compareTo(InitMilestone.PLUGINS_PREPARED) < 0) { return legacyInstances; // can't perform the auto discovery until all plugins are loaded, so just make the legacy instances visible - + } synchronized (getLoadLock()) { - if(extensions==null) { + if (extensions == null) { List<ExtensionComponent<T>> r = load(); r.addAll(legacyInstances); extensions = sort(r); @@ -217,22 +223,25 @@ public class ExtensionList<T> extends AbstractList<T> { * Chooses the object that locks the loading of the extension instances. */ protected Object getLoadLock() { - return hudson.lookup.setIfNull(Lock.class,new Lock()); + return hudson.lookup.setIfNull(Lock.class, new Lock()); } /** - * Loading an {@link ExtensionList} can result in a nested loading of another {@link ExtensionList}. - * What that means is that we need a single lock that spans across all the {@link ExtensionList}s, - * or else we can end up in a dead lock. + * Loading an {@link ExtensionList} can result in a nested loading of + * another {@link ExtensionList}. What that means is that we need a single + * lock that spans across all the {@link ExtensionList}s, or else we can end + * up in a dead lock. */ - private static final class Lock {} + private static final class Lock { + } /** * Loads all the extensions. */ protected List<ExtensionComponent<T>> load() { - if (LOGGER.isLoggable(Level.FINE)) - LOGGER.log(Level.FINE,"Loading ExtensionList: "+extensionType); + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, "Loading ExtensionList: " + extensionType); + } return hudson.getPluginManager().getPluginStrategy().findComponents(extensionType, hudson); } @@ -241,8 +250,8 @@ public class ExtensionList<T> extends AbstractList<T> { * If the {@link ExtensionList} implementation requires sorting extensions, * override this method to do so. * - * <p> - * The implementation should copy a list, do a sort, and return the new instance. + * <p> The implementation should copy a list, do a sort, and return the new + * instance. */ protected List<ExtensionComponent<T>> sort(List<ExtensionComponent<T>> r) { r = new ArrayList<ExtensionComponent<T>>(r); @@ -251,17 +260,16 @@ public class ExtensionList<T> extends AbstractList<T> { } public static <T> ExtensionList<T> create(Hudson hudson, Class<T> type) { - if(type.getAnnotation(LegacyInstancesAreScopedToHudson.class)!=null) - return new ExtensionList<T>(hudson,type); - else { - return new ExtensionList<T>(hudson,type,staticLegacyInstances.get(type)); + if (type.getAnnotation(LegacyInstancesAreScopedToHudson.class) != null) { + return new ExtensionList<T>(hudson, type); + } else { + return new ExtensionList<T>(hudson, type, staticLegacyInstances.get(type)); } } - /** * Places to store static-scope legacy instances. */ - private static final Memoizer<Class,CopyOnWriteArrayList> staticLegacyInstances = new Memoizer<Class,CopyOnWriteArrayList>() { + private static final Memoizer<Class, CopyOnWriteArrayList> staticLegacyInstances = new Memoizer<Class, CopyOnWriteArrayList>() { public CopyOnWriteArrayList compute(Class key) { return new CopyOnWriteArrayList(); } @@ -273,6 +281,5 @@ public class ExtensionList<T> extends AbstractList<T> { public static void clearLegacyInstances() { staticLegacyInstances.clear(); } - private static final Logger LOGGER = Logger.getLogger(ExtensionList.class.getName()); } diff --git a/hudson-core/src/main/java/hudson/ExtensionListView.java b/hudson-core/src/main/java/hudson/ExtensionListView.java index cf45d56..8005f0b 100644 --- a/hudson-core/src/main/java/hudson/ExtensionListView.java +++ b/hudson-core/src/main/java/hudson/ExtensionListView.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -28,23 +28,23 @@ import java.util.Collection; /** * Compatibility layer for legacy manual registration of extension points. * - * <p> - * Instances of this class can be created statically as a singleton, but it provides the view - * to {@link ExtensionList} of the current {@link Hudson}. - * Write operations to this list will update the legacy instances on {@link ExtensionList}. + * <p> Instances of this class can be created statically as a singleton, but it + * provides the view to {@link ExtensionList} of the current {@link Hudson}. + * Write operations to this list will update the legacy instances on + * {@link ExtensionList}. * - * <p> - * Whereas we used to use some simple data structure to keep track of static singletons, - * we can now use this instances, so that {@link ExtensionList} sees all the auto-registered - * and manually registered instances. + * <p> Whereas we used to use some simple data structure to keep track of static + * singletons, we can now use this instances, so that {@link ExtensionList} sees + * all the auto-registered and manually registered instances. * - * <p> - * Similarly, the old list (such as {@link UserNameResolver#LIST} continues to show all - * auto and manually registered instances, thus providing necessary bi-directional interoperability. + * <p> Similarly, the old list (such as {@link UserNameResolver#LIST} continues + * to show all auto and manually registered instances, thus providing necessary + * bi-directional interoperability. * * @author Kohsuke Kawaguchi */ public class ExtensionListView { + /** * Creates a plain {@link List} backed by the current {@link ExtensionList}. */ @@ -91,7 +91,8 @@ public class ExtensionListView { } /** - * Creates a enhanced {@link CopyOnWriteList} that acts as a view to the current {@link ExtensionList}. + * Creates a enhanced {@link CopyOnWriteList} that acts as a view to the + * current {@link ExtensionList}. */ public static <T> CopyOnWriteList<T> createCopyOnWriteList(final Class<T> type) { return new CopyOnWriteList<T>() { @@ -155,6 +156,5 @@ public class ExtensionListView { } }; } - // TODO: we need a few more types whose implementations get uglier } diff --git a/hudson-core/src/main/java/hudson/ExtensionPoint.java b/hudson-core/src/main/java/hudson/ExtensionPoint.java index 194ae3a..d6d0cc3 100644 --- a/hudson-core/src/main/java/hudson/ExtensionPoint.java +++ b/hudson-core/src/main/java/hudson/ExtensionPoint.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -24,29 +24,29 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** - * Marker interface that designates extensible components - * in Hudson that can be implemented by plugins. + * Marker interface that designates extensible components in Hudson that can be + * implemented by plugins. * - * <p> - * See respective interfaces/classes for more about how to register custom - * implementations to Hudson. See {@link Extension} for how to have - * Hudson auto-discover your implementations. + * <p> See respective interfaces/classes for more about how to register custom + * implementations to Hudson. See {@link Extension} for how to have Hudson + * auto-discover your implementations. * - * <p> - * This interface is used for auto-generating - * documentation. + * <p> This interface is used for auto-generating documentation. * * @author Kohsuke Kawaguchi * @see Plugin * @see Extension */ public interface ExtensionPoint { + /** - * Used by designers of extension points (direct subtypes of {@link ExtensionPoint}) to indicate that - * the legacy instances are scoped to {@link Hudson} instance. By default, legacy instances are - * static scope. + * Used by designers of extension points (direct subtypes of + * {@link ExtensionPoint}) to indicate that the legacy instances are scoped + * to {@link Hudson} instance. By default, legacy instances are static + * scope. */ @Target(TYPE) @Retention(RUNTIME) - public @interface LegacyInstancesAreScopedToHudson {} + public @interface LegacyInstancesAreScopedToHudson { + } } diff --git a/hudson-core/src/main/java/hudson/FeedAdapter.java b/hudson-core/src/main/java/hudson/FeedAdapter.java index 8b21503..81def6b 100644 --- a/hudson-core/src/main/java/hudson/FeedAdapter.java +++ b/hudson-core/src/main/java/hudson/FeedAdapter.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -21,37 +21,36 @@ import java.util.Calendar; /** * Provides a RSS feed view of the data. * - * <p> - * This interface allows data structure of any form to be exposed - * as RSS feeds, just by writing a stateless singleton adapter code that - * implements this interface. + * <p> This interface allows data structure of any form to be exposed as RSS + * feeds, just by writing a stateless singleton adapter code that implements + * this interface. * * @author Kohsuke Kawaguchi */ public interface FeedAdapter<E> { + /** - * Gets the human readable title of the entry. - * In RSS readers, this is usually displayed like an e-mail subject. + * Gets the human readable title of the entry. In RSS readers, this is + * usually displayed like an e-mail subject. */ String getEntryTitle(E entry); /** - * Gets the URL that represents this entry. - * Relative to context root of the Hudson. + * Gets the URL that represents this entry. Relative to context root of the + * Hudson. */ String getEntryUrl(E entry); /** - * Unique ID of each entry. - * RSS readers use this to determine what feeds are new and what are not. + * Unique ID of each entry. RSS readers use this to determine what feeds are + * new and what are not. * * This needs to produce a tag URL as per RFC 4151, required by Atom 1.0. */ String getEntryID(E entry); /** - * (Potentially lengthy) plain text to be attached to the feed. - * Can be null. + * (Potentially lengthy) plain text to be attached to the feed. Can be null. */ String getEntryDescription(E entry); diff --git a/hudson-core/src/main/java/hudson/FileSystemProvisioner.java b/hudson-core/src/main/java/hudson/FileSystemProvisioner.java index a6967cd..63e38da 100644 --- a/hudson-core/src/main/java/hudson/FileSystemProvisioner.java +++ b/hudson-core/src/main/java/hudson/FileSystemProvisioner.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -39,32 +39,26 @@ import java.io.OutputStream; * <p> * * - * <p> - * STILL A WORK IN PROGRESS. SUBJECT TO CHANGE! DO NOT EXTEND. - * - * TODO: is this per {@link Computer}? Per {@link Job}? - * -> probably per slave. - * - * <h2>Design Problems</h2> - * <ol> - * <li> - * Garbage collection of snapshots. When do we discard snapshots? - * In one use case, it would be convenient to keep the snapshot of the - * last promoted/successful build. So we need to define a mechanism - * to veto GC of snapshot? like an interface that Action can implement? - * - * Snapshot should be obtained per user's direction. That would be a good - * moment for the user to specify the retention policy. - * - * <li> - * Configuration mechanism. Should we auto-detect FileSystemProvisioner - * per OS? (but for example, zfs support would require the root access.) - * People probably needs to be able to disable this feature, which means - * one more configuration option. It's especially tricky because - * during the configuration we don't know the OS type. - * - * OTOH special slave type like the ones for network.com grid can - * hide this. + * <p> STILL A WORK IN PROGRESS. SUBJECT TO CHANGE! DO NOT EXTEND. + * + * TODO: is this per {@link Computer}? Per {@link Job}? -> probably per slave. + * + * <h2>Design Problems</h2> <ol> <li> Garbage collection of snapshots. When do + * we discard snapshots? In one use case, it would be convenient to keep the + * snapshot of the last promoted/successful build. So we need to define a + * mechanism to veto GC of snapshot? like an interface that Action can + * implement? + * + * Snapshot should be obtained per user's direction. That would be a good moment + * for the user to specify the retention policy. + * + * <li> Configuration mechanism. Should we auto-detect FileSystemProvisioner per + * OS? (but for example, zfs support would require the root access.) People + * probably needs to be able to disable this feature, which means one more + * configuration option. It's especially tricky because during the configuration + * we don't know the OS type. + * + * OTOH special slave type like the ones for network.com grid can hide this. * </ol> * * @@ -72,36 +66,31 @@ import java.io.OutputStream; * * To recap, * - * - when a slave connects, we auto-detect the file system provisioner. - * (for example, ZFS FSP would check the slave root user prop - * and/or attempt to "pfexec zfs create" and take over.) + * - when a slave connects, we auto-detect the file system provisioner. (for + * example, ZFS FSP would check the slave root user prop and/or attempt to + * "pfexec zfs create" and take over.) * - * - the user may configure jobs for snapshot collection, along with - * the retention policy. + * - the user may configure jobs for snapshot collection, along with the + * retention policy. * - * - keep workspace snapshots that correspond to the permalinks - * In ZFS, use a user property to remember the build and the job. + * - keep workspace snapshots that correspond to the permalinks In ZFS, use a + * user property to remember the build and the job. * - * Can't the 2nd step happen automatically, when someone else depends on - * the workspace snapshot of the upstream? Yes, by using {@link RunListener}. - * So this becomes like a special SCM type. + * Can't the 2nd step happen automatically, when someone else depends on the + * workspace snapshot of the upstream? Yes, by using {@link RunListener}. So + * this becomes like a special SCM type. * * * - * <h2>Design take 2</h2> - * <p> - * The first piece of this is the custom {@link SCM}, which inherits the - * workspace of another job. When this executes, it picks up - * {@link WorkspaceSnapshot} from the other job and use it to obtain the workspace. + * <h2>Design take 2</h2> <p> The first piece of this is the custom {@link SCM}, + * which inherits the workspace of another job. When this executes, it picks up + * {@link WorkspaceSnapshot} from the other job and use it to obtain the + * workspace. * - * <p> - * Then there's {@link RunListener}, which creates a snapshot if - * someone else is interested in using a snapshot later. + * <p> Then there's {@link RunListener}, which creates a snapshot if someone + * else is interested in using a snapshot later. * - * <h3>TODOs</h3> - * <ul> - * <li> - * Garbage collection of workspace snapshots. + * <h3>TODOs</h3> <ul> <li> Garbage collection of workspace snapshots. * * </ul> * @@ -109,67 +98,58 @@ import java.io.OutputStream; * @since 1.235 */ public abstract class FileSystemProvisioner implements ExtensionPoint, Describable<FileSystemProvisioner> { + /** - * Called very early in the build (before a build places any files - * in the workspace, such as SCM checkout) to provision a workspace - * for the build. + * Called very early in the build (before a build places any files in the + * workspace, such as SCM checkout) to provision a workspace for the build. * - * <p> - * This method can prepare the underlying file system in preparation - * for the later {@link #snapshot(AbstractBuild, FilePath, TaskListener)}. + * <p> This method can prepare the underlying file system in preparation for + * the later {@link #snapshot(AbstractBuild, FilePath, TaskListener)}. * - * TODO : the method needs to be able to see the snapshot would - * be later needed. In fact, perhaps we should only call this method - * when Hudson knows that a snapshot is later needed? + * TODO : the method needs to be able to see the snapshot would be later + * needed. In fact, perhaps we should only call this method when Hudson + * knows that a snapshot is later needed? * - * @param ws - * New workspace should be prepared in this location. This is the same value as - * {@code build.getProject().getWorkspace()} but passed separately for convenience. + * @param ws New workspace should be prepared in this location. This is the + * same value as {@code build.getProject().getWorkspace()} but passed + * separately for convenience. */ - public abstract void prepareWorkspace(AbstractBuild<?,?> build, FilePath ws, TaskListener listener) throws IOException, InterruptedException; + public abstract void prepareWorkspace(AbstractBuild<?, ?> build, FilePath ws, TaskListener listener) throws IOException, InterruptedException; /** * When a project is deleted, this method is called to undo the effect of * {@link #prepareWorkspace(AbstractBuild, FilePath, TaskListener)}. * - * @param project - * Project whose workspace is being discarded. - * @param ws - * Workspace to be discarded. This workspace is on the node - * this {@link FileSystemProvisioner} is provisioned for. + * @param project Project whose workspace is being discarded. + * @param ws Workspace to be discarded. This workspace is on the node this + * {@link FileSystemProvisioner} is provisioned for. */ public abstract void discardWorkspace(AbstractProject<?, ?> project, FilePath ws) throws IOException, InterruptedException; // public abstract void moveWorkspace(AbstractProject<?,?> project, File oldWorkspace, File newWorkspace) throws IOException; - /** * Obtains the snapshot of the workspace of the given build. * - * <p> - * The state of the build when this method is invoked depends on - * the project type. Most would call this at the end of the build, - * but for example {@link MatrixBuild} would call this after - * SCM check out so that the state of the fresh workspace - * can be then propagated to elsewhere. + * <p> The state of the build when this method is invoked depends on the + * project type. Most would call this at the end of the build, but for + * example {@link MatrixBuild} would call this after SCM check out so that + * the state of the fresh workspace can be then propagated to elsewhere. * - * <p> - * If the implementation of this method needs to store data in a file system, - * do so under {@link AbstractBuild#getRootDir()}, since the lifecycle of - * the snapshot is tied to the life cycle of a build. + * <p> If the implementation of this method needs to store data in a file + * system, do so under {@link AbstractBuild#getRootDir()}, since the + * lifecycle of the snapshot is tied to the life cycle of a build. * - * @param ws - * New workspace should be prepared in this location. This is the same value as - * {@code build.getProject().getWorkspace()} but passed separately for convenience. - * @param glob - * Ant-style file glob for files to include in the snapshot. May not be pertinent for all - * implementations. + * @param ws New workspace should be prepared in this location. This is the + * same value as {@code build.getProject().getWorkspace()} but passed + * separately for convenience. + * @param glob Ant-style file glob for files to include in the snapshot. May + * not be pertinent for all implementations. */ - public abstract WorkspaceSnapshot snapshot(AbstractBuild<?,?> build, FilePath ws, String glob, TaskListener listener) throws IOException, InterruptedException; + public abstract WorkspaceSnapshot snapshot(AbstractBuild<?, ?> build, FilePath ws, String glob, TaskListener listener) throws IOException, InterruptedException; public FileSystemProvisionerDescriptor getDescriptor() { return (FileSystemProvisionerDescriptor) Hudson.getInstance().getDescriptorOrDie(getClass()); } - /** * Default implementation. */ @@ -178,15 +158,16 @@ public abstract class FileSystemProvisioner implements ExtensionPoint, Describab /** * Returns all the registered {@link FileSystemProvisioner} descriptors. */ - public static DescriptorExtensionList<FileSystemProvisioner,FileSystemProvisionerDescriptor> all() { - return Hudson.getInstance().<FileSystemProvisioner,FileSystemProvisionerDescriptor>getDescriptorList(FileSystemProvisioner.class); + public static DescriptorExtensionList<FileSystemProvisioner, FileSystemProvisionerDescriptor> all() { + return Hudson.getInstance().<FileSystemProvisioner, FileSystemProvisionerDescriptor>getDescriptorList(FileSystemProvisioner.class); } /** - * Default implementation that doesn't rely on any file system specific capability, - * and thus can be used anywhere that Hudson runs. + * Default implementation that doesn't rely on any file system specific + * capability, and thus can be used anywhere that Hudson runs. */ public static final class Default extends FileSystemProvisioner { + public void prepareWorkspace(AbstractBuild<?, ?> build, FilePath ws, TaskListener listener) throws IOException, InterruptedException { } @@ -199,15 +180,15 @@ public abstract class FileSystemProvisioner implements ExtensionPoint, Describab public WorkspaceSnapshot snapshot(AbstractBuild<?, ?> build, FilePath ws, TaskListener listener) throws IOException, InterruptedException { return snapshot(build, ws, "**/*", listener); } - + /** * Creates a tar ball. */ public WorkspaceSnapshot snapshot(AbstractBuild<?, ?> build, FilePath ws, String glob, TaskListener listener) throws IOException, InterruptedException { - File wss = new File(build.getRootDir(),"workspace.zip"); + File wss = new File(build.getRootDir(), "workspace.zip"); OutputStream os = new BufferedOutputStream(new FileOutputStream(wss)); try { - ws.zip(os,glob); + ws.zip(os, glob); } finally { os.close(); } @@ -215,14 +196,16 @@ public abstract class FileSystemProvisioner implements ExtensionPoint, Describab } public static final class WorkspaceSnapshotImpl extends WorkspaceSnapshot { - public void restoreTo(AbstractBuild<?,?> owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException { - File wss = new File(owner.getRootDir(),"workspace.zip"); + + public void restoreTo(AbstractBuild<?, ?> owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException { + File wss = new File(owner.getRootDir(), "workspace.zip"); new FilePath(wss).unzip(dst); } } @Extension public static final class DescriptorImpl extends FileSystemProvisionerDescriptor { + public boolean discard(FilePath ws, TaskListener listener) throws IOException, InterruptedException { // the default provisioner doens't do anything special, // so allow other types to manage it diff --git a/hudson-core/src/main/java/hudson/FileSystemProvisionerDescriptor.java b/hudson-core/src/main/java/hudson/FileSystemProvisionerDescriptor.java index 33a1268..874af58 100644 --- a/hudson-core/src/main/java/hudson/FileSystemProvisionerDescriptor.java +++ b/hudson-core/src/main/java/hudson/FileSystemProvisionerDescriptor.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -27,38 +27,39 @@ import java.io.IOException; * @author Kohsuke Kawaguchi */ public abstract class FileSystemProvisionerDescriptor extends Descriptor<FileSystemProvisioner> implements ExtensionPoint { + /** - * Called to clean up a workspace that may potentially belong to this {@link FileSystemProvisioner}. + * Called to clean up a workspace that may potentially belong to this + * {@link FileSystemProvisioner}. * - * <p> - * Because users may modify the file system behind Hudson, and slaves may come and go when - * configuration changes hapen, in general case Hudson is unable to keep track of which jobs - * have workspaces in which slaves. + * <p> Because users may modify the file system behind Hudson, and slaves + * may come and go when configuration changes hapen, in general case Hudson + * is unable to keep track of which jobs have workspaces in which slaves. * - * <p> - * So instead we rey on a garbage collection mechanism, to look at workspaces left in the file system - * without the contextual information of the owner project, and try to clean that up. + * <p> So instead we rey on a garbage collection mechanism, to look at + * workspaces left in the file system without the contextual information of + * the owner project, and try to clean that up. * - * <p> - * This method is called to do this, after Hudson determines that the workspace should be deleted - * to reclaim disk space. The implementation of this method is expected to sniff the contents of - * the workspace, and if it looks like the one created by {@link FileSystemProvisioner#prepareWorkspace(AbstractBuild, FilePath, TaskListener)}, + * <p> This method is called to do this, after Hudson determines that the + * workspace should be deleted to reclaim disk space. The implementation of + * this method is expected to sniff the contents of the workspace, and if it + * looks like the one created by + * {@link FileSystemProvisioner#prepareWorkspace(AbstractBuild, FilePath, TaskListener)}, * perform the necessary deletion operation, and return <tt>true</tt>. * - * <p> - * If the workspace isn't the one created by this {@link FileSystemProvisioner}, or if the - * workspace can be simply deleted by {@link FilePath#deleteRecursive()}, then simply - * return <tt>false</tt> to give other {@link FileSystemProvisionerDescriptor}s a chance to + * <p> If the workspace isn't the one created by this + * {@link FileSystemProvisioner}, or if the workspace can be simply deleted + * by {@link FilePath#deleteRecursive()}, then simply return <tt>false</tt> + * to give other {@link FileSystemProvisionerDescriptor}s a chance to * discard them. * - * @param ws - * The workspace directory to be removed. - * @param listener - * The status of the operation, error message, etc., should go here. - * @return - * true if this {@link FileSystemProvisionerDescriptor} is responsible for de-alocating the workspace. - * false otherwise, in which case the other {@link FileSystemProvisionerDescriptor}s are asked to - * clean up the workspace. + * @param ws The workspace directory to be removed. + * @param listener The status of the operation, error message, etc., should + * go here. + * @return true if this {@link FileSystemProvisionerDescriptor} is + * responsible for de-alocating the workspace. false otherwise, in which + * case the other {@link FileSystemProvisionerDescriptor}s are asked to + * clean up the workspace. */ public abstract boolean discard(FilePath ws, TaskListener listener) throws IOException, InterruptedException; } diff --git a/hudson-core/src/main/java/hudson/GlobalMessage.java b/hudson-core/src/main/java/hudson/GlobalMessage.java index 9574332..6542872 100644 --- a/hudson-core/src/main/java/hudson/GlobalMessage.java +++ b/hudson-core/src/main/java/hudson/GlobalMessage.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ diff --git a/hudson-core/src/main/java/hudson/Indenter.java b/hudson-core/src/main/java/hudson/Indenter.java index ff904ca..4241235 100644 --- a/hudson-core/src/main/java/hudson/Indenter.java +++ b/hudson-core/src/main/java/hudson/Indenter.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -24,15 +24,18 @@ import hudson.model.Job; * @author Kohsuke Kawaguchi */ public abstract class Indenter<J extends Job> { + protected abstract int getNestLevel(J job); public final String getCss(J job) { - return "padding-left: "+getNestLevel(job)*2+"em"; + return "padding-left: " + getNestLevel(job) * 2 + "em"; } public final String getRelativeShift(J job) { int i = getNestLevel(job); - if(i==0) return null; - return "position:relative; left: "+ i *2+"em"; + if (i == 0) { + return null; + } + return "position:relative; left: " + i * 2 + "em"; } } diff --git a/hudson-core/src/main/java/hudson/Launcher.java b/hudson-core/src/main/java/hudson/Launcher.java index 099e035..2dde9bf 100644 --- a/hudson-core/src/main/java/hudson/Launcher.java +++ b/hudson-core/src/main/java/hudson/Launcher.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, Stephen Connolly - * + * Contributors: + * + * Kohsuke Kawaguchi, Stephen Connolly + * * *******************************************************************************/ @@ -51,28 +51,24 @@ import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM; /** * Starts a process. * - * <p> - * This hides the difference between running programs locally vs remotely. + * <p> This hides the difference between running programs locally vs remotely. * * - * <h2>'env' parameter</h2> - * <p> - * To allow important environment variables to be copied over to the remote machine, - * the 'env' parameter shouldn't contain default inherited environment variables - * (which often contains machine-specific information, like PATH, TIMEZONE, etc.) + * <h2>'env' parameter</h2> <p> To allow important environment variables to be + * copied over to the remote machine, the 'env' parameter shouldn't contain + * default inherited environment variables (which often contains + * machine-specific information, like PATH, TIMEZONE, etc.) * - * <p> - * {@link Launcher} is responsible for inheriting environment variables. + * <p> {@link Launcher} is responsible for inheriting environment variables. * * * @author Kohsuke Kawaguchi, Winston Prakash (bug fixes) * - * @see FilePath#createLauncher(TaskListener) + * @see FilePath#createLauncher(TaskListener) */ public abstract class Launcher { protected final TaskListener listener; - protected final VirtualChannel channel; public Launcher(TaskListener listener, VirtualChannel channel) { @@ -90,51 +86,54 @@ public abstract class Launcher { /** * Gets the channel that can be used to run a program remotely. * - * @return - * null if the target node is not configured to support this. - * this is a transitional measure. - * Note that a launcher for the master is always non-null. + * @return null if the target node is not configured to support this. this + * is a transitional measure. Note that a launcher for the master is always + * non-null. */ public VirtualChannel getChannel() { return channel; } /** - * Gets the {@link TaskListener} that this launcher uses to - * report the commands that it's executing. + * Gets the {@link TaskListener} that this launcher uses to report the + * commands that it's executing. */ public TaskListener getListener() { return listener; } /** - * If this {@link Launcher} is encapsulating an execution on a specific {@link Computer}, - * return it. + * If this {@link Launcher} is encapsulating an execution on a specific + * {@link Computer}, return it. * - * <p> - * Because of the way internal Hudson abstractions are set up (that is, {@link Launcher} only - * needs a {@link VirtualChannel} to do its job and isn't really required that the channel - * comes from an existing {@link Computer}), this method may not always the right {@link Computer} instance. + * <p> Because of the way internal Hudson abstractions are set up (that is, + * {@link Launcher} only needs a {@link VirtualChannel} to do its job and + * isn't really required that the channel comes from an existing + * {@link Computer}), this method may not always the right {@link Computer} + * instance. * - * @return - * null if this launcher is not created from a {@link Computer} object. - * @deprecated since 2008-11-16. - * See the javadoc for why this is inherently unreliable. If you are trying to - * figure out the current {@link Computer} from within a build, use - * {@link Computer#currentComputer()} + * @return null if this launcher is not created from a {@link Computer} + * object. + * @deprecated since 2008-11-16. See the javadoc for why this is inherently + * unreliable. If you are trying to figure out the current {@link Computer} + * from within a build, use {@link Computer#currentComputer()} */ public Computer getComputer() { - for( Computer c : Hudson.getInstance().getComputers() ) - if(c.getChannel()==channel) + for (Computer c : Hudson.getInstance().getComputers()) { + if (c.getChannel() == channel) { return c; + } + } return null; } /** * Builder pattern for configuring a process to launch. + * * @since 1.311 */ public final class ProcStarter { + protected List<String> commands; protected boolean[] masks; protected FilePath pwd; @@ -147,7 +146,7 @@ public abstract class Launcher { } public ProcStarter cmds(File program, String... args) { - commands = new ArrayList<String>(args.length+1); + commands = new ArrayList<String>(args.length + 1); commands.add(program.getPath()); commands.addAll(Arrays.asList(args)); return this; @@ -211,11 +210,11 @@ public abstract class Launcher { } /** - * Controls where the stderr of the process goes. - * By default, it's bundled into stdout. + * Controls where the stderr of the process goes. By default, it's + * bundled into stdout. */ public ProcStarter stderr(OutputStream err) { - this.stderr = err; + this.stderr = err; return this; } @@ -224,8 +223,8 @@ public abstract class Launcher { } /** - * Controls where the stdin of the process comes from. - * By default, <tt>/dev/null</tt>. + * Controls where the stdin of the process comes from. By default, + * <tt>/dev/null</tt>. */ public ProcStarter stdin(InputStream in) { this.stdin = in; @@ -239,18 +238,17 @@ public abstract class Launcher { /** * Sets the environment variable overrides. * - * <p> - * In adition to what the current process - * is inherited (if this is going to be launched from a slave agent, that - * becomes the "current" process), these variables will be also set. + * <p> In adition to what the current process is inherited (if this is + * going to be launched from a slave agent, that becomes the "current" + * process), these variables will be also set. */ public ProcStarter envs(Map<String, String> overrides) { return envs(Util.mapToEnv(overrides)); } /** - * @param overrides - * List of "VAR=VALUE". See {@link #envs(Map)} for the semantics. + * @param overrides List of "VAR=VALUE". See {@link #envs(Map)} for the + * semantics. */ public ProcStarter envs(String... overrides) { this.envs = overrides; @@ -284,263 +282,277 @@ public abstract class Launcher { } /** - * Launches a process by using a {@linkplain ProcStarter builder-pattern} to configure - * the parameters. + * Launches a process by using a {@linkplain ProcStarter builder-pattern} to + * configure the parameters. */ public final ProcStarter launch() { return new ProcStarter(); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ - public final Proc launch(String cmd, Map<String,String> env, OutputStream out, FilePath workDir) throws IOException { - return launch(cmd,Util.mapToEnv(env),out,workDir); + public final Proc launch(String cmd, Map<String, String> env, OutputStream out, FilePath workDir) throws IOException { + return launch(cmd, Util.mapToEnv(env), out, workDir); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, Map<String, String> env, OutputStream out, FilePath workDir) throws IOException { return launch(cmd, Util.mapToEnv(env), out, workDir); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, Map<String, String> env, InputStream in, OutputStream out) throws IOException { return launch(cmd, Util.mapToEnv(env), in, out); } /** - * Launch a command with optional censoring of arguments from the listener (Note: <strong>The censored portions will - * remain visible through /proc, pargs, process explorer, etc. i.e. people logged in on the same machine</strong> - * This version of the launch command just ensures that it is not visible from a build log which is exposed via the - * web) + * Launch a command with optional censoring of arguments from the listener + * (Note: <strong>The censored portions will remain visible through /proc, + * pargs, process explorer, etc. i.e. people logged in on the same + * machine</strong> This version of the launch command just ensures that it + * is not visible from a build log which is exposed via the web) * - * @param cmd The command and all it's arguments. - * @param mask Which of the command and arguments should be masked from the listener - * @param env Environment variable overrides. - * @param out stdout and stderr of the process will be sent to this stream. the stream won't be closed. + * @param cmd The command and all it's arguments. + * @param mask Which of the command and arguments should be masked from the + * listener + * @param env Environment variable overrides. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * @param workDir null if the working directory could be anything. * @return The process of the command. * @throws IOException When there are IO problems. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, boolean[] mask, Map<String, String> env, OutputStream out, FilePath workDir) throws IOException { return launch(cmd, mask, Util.mapToEnv(env), out, workDir); } /** - * Launch a command with optional censoring of arguments from the listener (Note: <strong>The censored portions will - * remain visible through /proc, pargs, process explorer, etc. i.e. people logged in on the same machine</strong> - * This version of the launch command just ensures that it is not visible from a build log which is exposed via the - * web) + * Launch a command with optional censoring of arguments from the listener + * (Note: <strong>The censored portions will remain visible through /proc, + * pargs, process explorer, etc. i.e. people logged in on the same + * machine</strong> This version of the launch command just ensures that it + * is not visible from a build log which is exposed via the web) * - * @param cmd The command and all it's arguments. - * @param mask Which of the command and arguments should be masked from the listener - * @param env Environment variable overrides. - * @param in null if there's no input. - * @param out stdout and stderr of the process will be sent to this stream. the stream won't be closed. + * @param cmd The command and all it's arguments. + * @param mask Which of the command and arguments should be masked from the + * listener + * @param env Environment variable overrides. + * @param in null if there's no input. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * @return The process of the command. * @throws IOException When there are IO problems. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, boolean[] mask, Map<String, String> env, InputStream in, OutputStream out) throws IOException { return launch(cmd, mask, Util.mapToEnv(env), in, out); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ - public final Proc launch(String cmd,String[] env,OutputStream out, FilePath workDir) throws IOException { - return launch(Util.tokenize(cmd),env,out,workDir); + public final Proc launch(String cmd, String[] env, OutputStream out, FilePath workDir) throws IOException { + return launch(Util.tokenize(cmd), env, out, workDir); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, String[] env, OutputStream out, FilePath workDir) throws IOException { return launch(cmd, env, null, out, workDir); } /** - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, String[] env, InputStream in, OutputStream out) throws IOException { return launch(cmd, env, in, out, null); } /** - * Launch a command with optional censoring of arguments from the listener (Note: <strong>The censored portions will - * remain visible through /proc, pargs, process explorer, etc. i.e. people logged in on the same machine</strong> - * This version of the launch command just ensures that it is not visible from a build log which is exposed via the - * web) + * Launch a command with optional censoring of arguments from the listener + * (Note: <strong>The censored portions will remain visible through /proc, + * pargs, process explorer, etc. i.e. people logged in on the same + * machine</strong> This version of the launch command just ensures that it + * is not visible from a build log which is exposed via the web) * - * @param cmd The command and all it's arguments. - * @param mask Which of the command and arguments should be masked from the listener - * @param env Environment variable overrides. - * @param out stdout and stderr of the process will be sent to this stream. the stream won't be closed. + * @param cmd The command and all it's arguments. + * @param mask Which of the command and arguments should be masked from the + * listener + * @param env Environment variable overrides. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * @param workDir null if the working directory could be anything. * @return The process of the command. * @throws IOException When there are IO problems. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, boolean[] mask, String[] env, OutputStream out, FilePath workDir) throws IOException { return launch(cmd, mask, env, null, out, workDir); } /** - * Launch a command with optional censoring of arguments from the listener (Note: <strong>The censored portions will - * remain visible through /proc, pargs, process explorer, etc. i.e. people logged in on the same machine</strong> - * This version of the launch command just ensures that it is not visible from a build log which is exposed via the - * web) + * Launch a command with optional censoring of arguments from the listener + * (Note: <strong>The censored portions will remain visible through /proc, + * pargs, process explorer, etc. i.e. people logged in on the same + * machine</strong> This version of the launch command just ensures that it + * is not visible from a build log which is exposed via the web) * - * @param cmd The command and all it's arguments. - * @param mask Which of the command and arguments should be masked from the listener - * @param env Environment variable overrides. - * @param in null if there's no input. - * @param out stdout and stderr of the process will be sent to this stream. the stream won't be closed. + * @param cmd The command and all it's arguments. + * @param mask Which of the command and arguments should be masked from the + * listener + * @param env Environment variable overrides. + * @param in null if there's no input. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * @return The process of the command. * @throws IOException When there are IO problems. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public final Proc launch(String[] cmd, boolean[] mask, String[] env, InputStream in, OutputStream out) throws IOException { return launch(cmd, mask, env, in, out, null); } /** - * @param env - * Environment variable overrides. - * @param in - * null if there's no input. - * @param workDir - * null if the working directory could be anything. - * @param out - * stdout and stderr of the process will be sent to this stream. - * the stream won't be closed. + * @param env Environment variable overrides. + * @param in null if there's no input. + * @param workDir null if the working directory could be anything. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public Proc launch(String[] cmd, String[] env, InputStream in, OutputStream out, FilePath workDir) throws IOException { return launch(launch().cmds(cmd).envs(env).stdin(in).stdout(out).pwd(workDir)); } /** - * Launch a command with optional censoring of arguments from the listener (Note: <strong>The censored portions will - * remain visible through /proc, pargs, process explorer, etc. i.e. people logged in on the same machine</strong> - * This version of the launch command just ensures that it is not visible from a build log which is exposed via the - * web) + * Launch a command with optional censoring of arguments from the listener + * (Note: <strong>The censored portions will remain visible through /proc, + * pargs, process explorer, etc. i.e. people logged in on the same + * machine</strong> This version of the launch command just ensures that it + * is not visible from a build log which is exposed via the web) * - * @param cmd The command and all it's arguments. - * @param mask Which of the command and arguments should be masked from the listener - * @param env Environment variable overrides. - * @param in null if there's no input. - * @param out stdout and stderr of the process will be sent to this stream. the stream won't be closed. + * @param cmd The command and all it's arguments. + * @param mask Which of the command and arguments should be masked from the + * listener + * @param env Environment variable overrides. + * @param in null if there's no input. + * @param out stdout and stderr of the process will be sent to this stream. + * the stream won't be closed. * @param workDir null if the working directory could be anything. * @return The process of the command. * @throws IOException When there are IO problems. * - * @deprecated as of 1.311 - * Use {@link #launch()} and its associated builder pattern + * @deprecated as of 1.311 Use {@link #launch()} and its associated builder + * pattern */ public Proc launch(String[] cmd, boolean[] mask, String[] env, InputStream in, OutputStream out, FilePath workDir) throws IOException { return launch(launch().cmds(cmd).masks(mask).envs(env).stdin(in).stdout(out).pwd(workDir)); } /** - * Primarily invoked from {@link ProcStarter#start()} to start a process with a specific launcher. + * Primarily invoked from {@link ProcStarter#start()} to start a process + * with a specific launcher. */ public abstract Proc launch(ProcStarter starter) throws IOException; /** - * Launches a specified process and connects its input/output to a {@link Channel}, then - * return it. + * Launches a specified process and connects its input/output to a + * {@link Channel}, then return it. * - * <p> - * When the returned channel is terminated, the process will be killed. + * <p> When the returned channel is terminated, the process will be killed. * - * @param out - * Where the stderr from the launched process will be sent. - * @param workDir - * The working directory of the new process, or null to inherit - * from the current process - * @param envVars - * Environment variable overrides. In addition to what the current process - * is inherited (if this is going to be launched from a slave agent, that - * becomes the "current" process), these variables will be also set. + * @param out Where the stderr from the launched process will be sent. + * @param workDir The working directory of the new process, or null to + * inherit from the current process + * @param envVars Environment variable overrides. In addition to what the + * current process is inherited (if this is going to be launched from a + * slave agent, that becomes the "current" process), these variables will be + * also set. */ - public abstract Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String,String> envVars) throws IOException, InterruptedException; + public abstract Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException; /** * Returns true if this {@link Launcher} is going to launch on Unix. */ public boolean isUnix() { - return File.pathSeparatorChar==':'; + return File.pathSeparatorChar == ':'; } /** * Calls {@link ProcessTree#killAll(Map)} to kill processes. */ - public abstract void kill(Map<String,String> modelEnvVars) throws IOException, InterruptedException; + public abstract void kill(Map<String, String> modelEnvVars) throws IOException, InterruptedException; /** - * Prints out the command line to the listener so that users know what we are doing. + * Prints out the command line to the listener so that users know what we + * are doing. */ protected final void printCommandLine(String[] cmd, FilePath workDir) { StringBuilder buf = new StringBuilder(); if (workDir != null) { buf.append('['); - if(showFullPath) + if (showFullPath) { buf.append(workDir.getRemote()); - else + } else { buf.append(workDir.getRemote().replaceFirst("^.+[/\\\\]", "")); + } buf.append("] "); } buf.append('$'); for (String c : cmd) { buf.append(' '); - if(c.indexOf(' ')>=0) { - if(c.indexOf('"')>=0) + if (c.indexOf(' ') >= 0) { + if (c.indexOf('"') >= 0) { buf.append('\'').append(c).append('\''); - else + } else { buf.append('"').append(c).append('"'); - } else + } + } else { buf.append(c); + } } listener.getLogger().println(buf.toString()); } /** - * Prints out the command line to the listener with some portions masked to prevent sensitive information from being - * recorded on the listener. + * Prints out the command line to the listener with some portions masked to + * prevent sensitive information from being recorded on the listener. * - * @param cmd The commands - * @param mask An array of booleans which control whether a cmd element should be masked (<code>true</code>) or - * remain unmasked (<code>false</code>). + * @param cmd The commands + * @param mask An array of booleans which control whether a cmd element + * should be masked (<code>true</code>) or remain unmasked + * (<code>false</code>). * @param workDir The work dir. */ protected final void maskedPrintCommandLine(List<String> cmd, boolean[] mask, FilePath workDir) { - if(mask==null) { - printCommandLine(cmd.toArray(new String[cmd.size()]),workDir); + if (mask == null) { + printCommandLine(cmd.toArray(new String[cmd.size()]), workDir); return; } - + assert mask.length == cmd.size(); final String[] masked = new String[cmd.size()]; for (int i = 0; i < cmd.size(); i++) { @@ -552,8 +564,9 @@ public abstract class Launcher { } printCommandLine(masked, workDir); } + protected final void maskedPrintCommandLine(String[] cmd, boolean[] mask, FilePath workDir) { - maskedPrintCommandLine(Arrays.asList(cmd),mask,workDir); + maskedPrintCommandLine(Arrays.asList(cmd), mask, workDir); } /** @@ -561,14 +574,15 @@ public abstract class Launcher { */ public final Launcher decorateFor(Node node) { Launcher l = this; - for (LauncherDecorator d : LauncherDecorator.all()) - l = d.decorate(l,node); + for (LauncherDecorator d : LauncherDecorator.all()) { + l = d.decorate(l, node); + } return l; } /** - * Returns a decorated {@link Launcher} that puts the given set of arguments as a prefix to any commands - * that it invokes. + * Returns a decorated {@link Launcher} that puts the given set of arguments + * as a prefix to any commands that it invokes. * * @since 1.299 */ @@ -577,14 +591,14 @@ public abstract class Launcher { return new Launcher(outer) { @Override public Proc launch(ProcStarter starter) throws IOException { - starter.commands.addAll(0,Arrays.asList(prefix)); + starter.commands.addAll(0, Arrays.asList(prefix)); starter.masks = prefix(starter.masks); return outer.launch(starter); } @Override public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException { - return outer.launchChannel(prefix(cmd),out,workDir,envVars); + return outer.launchChannel(prefix(cmd), out, workDir, envVars); } @Override @@ -593,15 +607,15 @@ public abstract class Launcher { } private String[] prefix(String[] args) { - String[] newArgs = new String[args.length+prefix.length]; - System.arraycopy(prefix,0,newArgs,0,prefix.length); - System.arraycopy(args,0,newArgs,prefix.length,args.length); + String[] newArgs = new String[args.length + prefix.length]; + System.arraycopy(prefix, 0, newArgs, 0, prefix.length); + System.arraycopy(args, 0, newArgs, prefix.length, args.length); return newArgs; } private boolean[] prefix(boolean[] args) { - boolean[] newArgs = new boolean[args.length+prefix.length]; - System.arraycopy(args,0,newArgs,prefix.length,args.length); + boolean[] newArgs = new boolean[args.length + prefix.length]; + System.arraycopy(args, 0, newArgs, prefix.length, args.length); return newArgs; } }; @@ -611,8 +625,9 @@ public abstract class Launcher { * {@link Launcher} that launches process locally. */ public static class LocalLauncher extends Launcher { + public LocalLauncher(TaskListener listener) { - this(listener,Hudson.MasterComputer.localChannel); + this(listener, Hudson.MasterComputer.localChannel); } public LocalLauncher(TaskListener listener, VirtualChannel channel) { @@ -627,22 +642,25 @@ public abstract class Launcher { // replace variables in command line String[] jobCmd = new String[ps.commands.size()]; - for ( int idx = 0 ; idx < jobCmd.length; idx++ ) - jobCmd[idx] = jobEnv.expand(ps.commands.get(idx)); + for (int idx = 0; idx < jobCmd.length; idx++) { + jobCmd[idx] = jobEnv.expand(ps.commands.get(idx)); + } return new LocalProc(jobCmd, Util.mapToEnv(jobEnv), ps.stdin, ps.stdout, ps.stderr, toFile(ps.pwd)); } private File toFile(FilePath f) { - return f==null ? null : new File(f.getRemote()); + return f == null ? null : new File(f.getRemote()); } - public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String,String> envVars) throws IOException { + public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException { printCommandLine(cmd, workDir); ProcessBuilder pb = new ProcessBuilder(cmd); pb.directory(toFile(workDir)); - if (envVars!=null) pb.environment().putAll(envVars); + if (envVars != null) { + pb.environment().putAll(envVars); + } return launchChannel(out, pb); } @@ -653,8 +671,7 @@ public abstract class Launcher { } /** - * @param out - * Where the stderr from the launched process will be sent. + * @param out Where the stderr from the launched process will be sent. */ public Channel launchChannel(OutputStream out, ProcessBuilder pb) throws IOException { final EnvVars cookie = EnvVars.createCookie(); @@ -662,13 +679,12 @@ public abstract class Launcher { final Process proc = pb.start(); - final Thread t2 = new StreamCopyThread(pb.command()+": stderr copier", proc.getErrorStream(), out); + final Thread t2 = new StreamCopyThread(pb.command() + ": stderr copier", proc.getErrorStream(), out); t2.start(); final NativeUtils nativeUtils = NativeUtils.getInstance(); - return new Channel("locally launched channel on "+ pb.command(), - Computer.threadPoolForRemoting, proc.getInputStream(), proc.getOutputStream(), out) { - + return new Channel("locally launched channel on " + pb.command(), + Computer.threadPoolForRemoting, proc.getInputStream(), proc.getOutputStream(), out) { /** * Kill the process when the channel is severed. */ @@ -677,7 +693,7 @@ public abstract class Launcher { super.terminate(e); ProcessTree pt = ProcessTree.get(nativeUtils); try { - pt.killAll(proc,cookie); + pt.killAll(proc, cookie); } catch (InterruptedException x) { LOGGER.log(Level.INFO, "Interrupted", x); } @@ -702,6 +718,7 @@ public abstract class Launcher { * Launches processes remotely by using the given channel. */ public static class RemoteLauncher extends Launcher { + private final boolean isUnix; public RemoteLauncher(TaskListener listener, VirtualChannel channel, boolean isUnix) { @@ -711,23 +728,23 @@ public abstract class Launcher { public Proc launch(ProcStarter ps) throws IOException { final OutputStream out = ps.stdout == null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stdout)); - final OutputStream err = ps.stderr==null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stderr)); - final InputStream in = ps.stdin==null ? null : new RemoteInputStream(ps.stdin); - final String workDir = ps.pwd==null ? null : ps.pwd.getRemote(); + final OutputStream err = ps.stderr == null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stderr)); + final InputStream in = ps.stdin == null ? null : new RemoteInputStream(ps.stdin); + final String workDir = ps.pwd == null ? null : ps.pwd.getRemote(); return new RemoteProc(getChannel().callAsync(new RemoteLaunchCallable(ps.commands, ps.masks, ps.envs, in, out, err, workDir, listener))); } - public Channel launchChannel(String[] cmd, OutputStream err, FilePath _workDir, Map<String,String> envOverrides) throws IOException, InterruptedException { + public Channel launchChannel(String[] cmd, OutputStream err, FilePath _workDir, Map<String, String> envOverrides) throws IOException, InterruptedException { printCommandLine(cmd, _workDir); Pipe out = Pipe.createRemoteToLocal(); - final String workDir = _workDir==null ? null : _workDir.getRemote(); + final String workDir = _workDir == null ? null : _workDir.getRemote(); OutputStream os = getChannel().call(new RemoteChannelLaunchCallable(cmd, out, err, workDir, envOverrides)); - return new Channel("remotely launched channel on "+channel, - Computer.threadPoolForRemoting, out.getIn(), new BufferedOutputStream(os)); + return new Channel("remotely launched channel on " + channel, + Computer.threadPoolForRemoting, out.getIn(), new BufferedOutputStream(os)); } @Override @@ -736,11 +753,12 @@ public abstract class Launcher { } @Override - public void kill(final Map<String,String> modelEnvVars) throws IOException, InterruptedException { + public void kill(final Map<String, String> modelEnvVars) throws IOException, InterruptedException { getChannel().call(new KillTask(modelEnvVars, NativeUtils.getInstance())); } - private static final class KillTask implements Callable<Void,RuntimeException> { + private static final class KillTask implements Callable<Void, RuntimeException> { + private final Map<String, String> modelEnvVars; private final NativeUtils nativeUtils; @@ -757,12 +775,12 @@ public abstract class Launcher { } return null; } - private static final long serialVersionUID = 1L; } } - private static class RemoteLaunchCallable implements Callable<Integer,IOException> { + private static class RemoteLaunchCallable implements Callable<Integer, IOException> { + private final List<String> cmd; private final boolean[] masks; private final String[] env; @@ -786,14 +804,16 @@ public abstract class Launcher { public Integer call() throws IOException { Launcher.ProcStarter ps = new LocalLauncher(listener).launch(); ps.cmds(cmd).masks(masks).envs(env).stdin(in).stdout(out).stderr(err); - if(workDir!=null) ps.pwd(workDir); + if (workDir != null) { + ps.pwd(workDir); + } Proc p = ps.start(); try { return p.join(); } catch (InterruptedException e) { return -1; - } finally{ + } finally { try { // Fix: http://issues.hudson-ci.org/browse/HUDSON-7809 // This call should not return immediately after the @@ -807,18 +827,18 @@ public abstract class Launcher { } } } - private static final long serialVersionUID = 1L; } - private static class RemoteChannelLaunchCallable implements Callable<OutputStream,IOException> { + private static class RemoteChannelLaunchCallable implements Callable<OutputStream, IOException> { + private final String[] cmd; private final Pipe out; private final String workDir; private final OutputStream err; - private final Map<String,String> envOverrides; + private final Map<String, String> envOverrides; - public RemoteChannelLaunchCallable(String[] cmd, Pipe out, OutputStream err, String workDir, Map<String,String> envOverrides) { + public RemoteChannelLaunchCallable(String[] cmd, Pipe out, OutputStream err, String workDir, Map<String, String> envOverrides) { this.cmd = cmd; this.out = out; this.err = new RemoteOutputStream(err); @@ -828,33 +848,33 @@ public abstract class Launcher { public OutputStream call() throws IOException { Process p = Runtime.getRuntime().exec(cmd, - Util.mapToEnv(inherit(envOverrides)), - workDir == null ? null : new File(workDir)); + Util.mapToEnv(inherit(envOverrides)), + workDir == null ? null : new File(workDir)); List<String> cmdLines = Arrays.asList(cmd); - new StreamCopyThread("stdin copier for remote agent on "+cmdLines, - p.getInputStream(), out.getOut()).start(); - new StreamCopyThread("stderr copier for remote agent on "+cmdLines, - p.getErrorStream(), err).start(); + new StreamCopyThread("stdin copier for remote agent on " + cmdLines, + p.getInputStream(), out.getOut()).start(); + new StreamCopyThread("stderr copier for remote agent on " + cmdLines, + p.getErrorStream(), err).start(); // TODO: don't we need to join? return new RemoteOutputStream(p.getOutputStream()); } - private static final long serialVersionUID = 1L; } /** - * Expands the list of environment variables by inheriting current env variables. + * Expands the list of environment variables by inheriting current env + * variables. */ private static EnvVars inherit(String[] env) { // convert String[] to Map first EnvVars m = new EnvVars(); - if(env!=null) { + if (env != null) { for (String e : env) { int index = e.indexOf('='); - m.put(e.substring(0,index), e.substring(index+1)); + m.put(e.substring(0, index), e.substring(index + 1)); } } // then do the inheritance @@ -862,19 +882,19 @@ public abstract class Launcher { } /** - * Expands the list of environment variables by inheriting current env variables. + * Expands the list of environment variables by inheriting current env + * variables. */ - private static EnvVars inherit(Map<String,String> overrides) { + private static EnvVars inherit(Map<String, String> overrides) { EnvVars m = new EnvVars(EnvVars.masterEnvVars); - for (Map.Entry<String,String> o : overrides.entrySet()) - m.override(o.getKey(),m.expand(o.getValue())); + for (Map.Entry<String, String> o : overrides.entrySet()) { + m.override(o.getKey(), m.expand(o.getValue())); + } return m; } - /** * Debug option to display full current path instead of just the last token. */ public static boolean showFullPath = false; - private static final Logger LOGGER = Logger.getLogger(Launcher.class.getName()); } diff --git a/hudson-core/src/main/java/hudson/LauncherDecorator.java b/hudson-core/src/main/java/hudson/LauncherDecorator.java index adf2546..f86d90a 100644 --- a/hudson-core/src/main/java/hudson/LauncherDecorator.java +++ b/hudson-core/src/main/java/hudson/LauncherDecorator.java @@ -8,7 +8,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * + * * *******************************************************************************/ @@ -21,35 +21,36 @@ import hudson.tasks.BuildWrapper; /** * Decorates {@link Launcher} so that one can intercept executions of commands - * and alters the command being executed, such as doing this in fakeroot, sudo, pfexec, etc. + * and alters the command being executed, such as doing this in fakeroot, sudo, + * pfexec, etc. * * @author Kohsuke Kawaguchi * @since 1.299 * @see BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener) */ public abstract class LauncherDecorator implements ExtensionPoint { + /** - * Called from {@link Node#createLauncher(TaskListener)} to decorate the launchers. + * Called from {@link Node#createLauncher(TaskListener)} to decorate the + * launchers. * - * <p> - * This method should perform node-specific decoration. For job-specific decoration, - * {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} might - * fit your needs better. + * <p> This method should perform node-specific decoration. For job-specific + * decoration, + * {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} + * might fit your needs better. * - * <p> - * If the implementation wants to do something differently if the launcher is - * for a build, call {@link Executor#currentExecutor()}. If it returns non-null - * you can figure out the current build in progress from there. Note that - * {@link Launcher}s are also created for doing things other than builds, - * so {@link Executor#currentExecutor()} may return null. Also, for job-specific - * decoration, see {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} as well. + * <p> If the implementation wants to do something differently if the + * launcher is for a build, call {@link Executor#currentExecutor()}. If it + * returns non-null you can figure out the current build in progress from + * there. Note that {@link Launcher}s are also created for doing things + * other than builds, so {@link Executor#currentExecutor()} may return null. + * Also, for job-specific decoration, see + * {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} + * as well. * - * @param launcher - * The base launcher that you can decorate. Never null. - * @param node - * Node for which this launcher is created. Never null. - * @return - * Never null. Return the 'launcher' parameter to do no-op. + * @param launcher The base launcher that you can decorate. Never null. + * @param node Node for which this launcher is created. Never null. + * @return Never null. Return the 'launcher' parameter to do no-op. * @see Launcher#decorateFor(Node) * @see Launcher#decorateByPrefix(String[]) */ diff --git a/hudson-core/src/main/java/hudson/LocalPluginManager.java b/hudson-core/src/main/java/hudson/LocalPluginManager.java index dbd2a80..292b0bd 100644 --- a/hudson-core/src/main/java/hudson/LocalPluginManager.java +++ b/hudson-core/src/main/java/hudson/LocalPluginManager.java @@ -7,9 +7,9 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * * - * * Kohsuke Kawaguchi * *******************************************************************************/ @@ -34,17 +34,20 @@ import java.util.logging.Logger; * @author Kohsuke Kawaguchi */ public class LocalPluginManager extends PluginManager { + private final Hudson hudson; + public LocalPluginManager(Hudson hudson) { - super(hudson.servletContext, new File(hudson.getRootDir(),"plugins")); + super(hudson.servletContext, new File(hudson.getRootDir(), "plugins")); this.hudson = hudson; } /** - * If the war file has any "/WEB-INF/plugins/*.hpi", extract them into the plugin directory. + * If the war file has any "/WEB-INF/plugins/*.hpi", extract them into the + * plugin directory. * - * @return - * File names of the bundled plugins. Like {"ssh-slaves.hpi","subvesrion.hpi"} + * @return File names of the bundled plugins. Like + * {"ssh-slaves.hpi","subvesrion.hpi"} */ @Override protected Collection<String> loadBundledPlugins() { @@ -55,9 +58,9 @@ public class LocalPluginManager extends PluginManager { Set<String> names = new HashSet<String>(); - for( String path : Util.fixNull((Set<String>)hudson.servletContext.getResourcePaths("/WEB-INF/plugins"))) { - String fileName = path.substring(path.lastIndexOf('/')+1); - if(fileName.length()==0) { + for (String path : Util.fixNull((Set<String>) hudson.servletContext.getResourcePaths("/WEB-INF/plugins"))) { + String fileName = path.substring(path.lastIndexOf('/') + 1); + if (fileName.length() == 0) { // see http://www.nabble.com/404-Not-Found-error-when-clicking-on-help-td24508544.html // I suspect some containers are returning directory names. continue; @@ -68,12 +71,11 @@ public class LocalPluginManager extends PluginManager { URL url = hudson.servletContext.getResource(path); copyBundledPlugin(url, fileName); } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Failed to extract the bundled plugin "+fileName,e); + LOGGER.log(Level.SEVERE, "Failed to extract the bundled plugin " + fileName, e); } } return names; } - private static final Logger LOGGER = Logger.getLogger(LocalPluginManager.class.getName()); } diff --git a/hudson-core/src/main/java/hudson/Lookup.java b/hudson-core/src/main/java/hudson/Lookup.java index 3881d75..ddbd1b3 100644 --- a/hudson-core/src/main/java/hudson/Lookup.java +++ b/hudson-core/src/main/java/hudson/Lookup.java @@ -7,9 +7,9 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * * - * * Kohsuke Kawaguchi * *******************************************************************************/ @@ -24,26 +24,28 @@ import java.util.concurrent.ConcurrentHashMap; * @author Kohsuke Kawaguchi */ public class Lookup { - private final ConcurrentHashMap<Class,Object> data = new ConcurrentHashMap<Class,Object>(); + + private final ConcurrentHashMap<Class, Object> data = new ConcurrentHashMap<Class, Object>(); public <T> T get(Class<T> type) { return type.cast(data.get(type)); } public <T> T set(Class<T> type, T instance) { - return type.cast(data.put(type,instance)); + return type.cast(data.put(type, instance)); } /** * Overwrites the value only if the current value is null. * - * @return - * If the value was null, return the {@code instance} value. - * Otherwise return the current value, which is non-null. + * @return If the value was null, return the {@code instance} value. + * Otherwise return the current value, which is non-null. */ public <T> T setIfNull(Class<T> type, T instance) { Object o = data.putIfAbsent(type, instance); - if (o!=null) return type.cast(o); + if (o != null) { + return type.cast(o); + } return instance; } } diff --git a/hudson-core/src/main/java/hudson/Main.java b/hudson-core/src/main/java/hudson/Main.java index 7944e86..21ce66a 100644 --- a/hudson-core/src/main/java/hudson/Main.java +++ b/hudson-core/src/main/java/hudson/Main.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -39,12 +39,12 @@ import java.nio.charset.Charset; /** * Entry point to Hudson from command line. * - * <p> - * This tool runs another process and sends its result to Hudson. + * <p> This tool runs another process and sends its result to Hudson. * * @author Kohsuke Kawaguchi */ public class Main { + public static void main(String[] args) { try { System.exit(run(args)); @@ -56,7 +56,7 @@ public class Main { public static int run(String[] args) throws Exception { String home = getHudsonHome(); - if (home==null) { + if (home == null) { System.err.println("HUDSON_HOME is not set."); return -1; } @@ -79,31 +79,38 @@ public class Main { String projectName = args[0]; String home = getHudsonHome(); - if(!home.endsWith("/")) home = home + '/'; // make sure it ends with '/' - + if (!home.endsWith("/")) { + home = home + '/'; // make sure it ends with '/' + } // check for authentication info String auth = new URL(home).getUserInfo(); - if(auth != null) auth = "Basic " + new Base64Encoder().encode(auth.getBytes("UTF-8")); + if (auth != null) { + auth = "Basic " + new Base64Encoder().encode(auth.getBytes("UTF-8")); + } {// check if the home is set correctly HttpURLConnection con = open(new URL(home)); - if (auth != null) con.setRequestProperty("Authorization", auth); + if (auth != null) { + con.setRequestProperty("Authorization", auth); + } con.connect(); - if(con.getResponseCode()!=200 - || con.getHeaderField("X-Hudson")==null) { - System.err.println(home+" is not Hudson ("+con.getResponseMessage()+")"); + if (con.getResponseCode() != 200 + || con.getHeaderField("X-Hudson") == null) { + System.err.println(home + " is not Hudson (" + con.getResponseMessage() + ")"); return -1; } } - String projectNameEnc = URLEncoder.encode(projectName,"UTF-8").replaceAll("\\+","%20"); + String projectNameEnc = URLEncoder.encode(projectName, "UTF-8").replaceAll("\\+", "%20"); {// check if the job name is correct - HttpURLConnection con = open(new URL(home+"job/"+projectNameEnc+"/acceptBuildResult")); - if (auth != null) con.setRequestProperty("Authorization", auth); + HttpURLConnection con = open(new URL(home + "job/" + projectNameEnc + "/acceptBuildResult")); + if (auth != null) { + con.setRequestProperty("Authorization", auth); + } con.connect(); - if(con.getResponseCode()!=200) { - System.err.println(projectName+" is not a valid job name on "+home+" ("+con.getResponseMessage()+")"); + if (con.getResponseCode() != 200) { + System.err.println(projectName + " is not a valid job name on " + home + " (" + con.getResponseMessage() + ")"); return -1; } } @@ -111,9 +118,11 @@ public class Main { // get a crumb to pass the csrf check String crumbField = null, crumbValue = null; try { - HttpURLConnection con = open(new URL(home + - "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)'")); - if (auth != null) con.setRequestProperty("Authorization", auth); + HttpURLConnection con = open(new URL(home + + "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)'")); + if (auth != null) { + con.setRequestProperty("Authorization", auth); + } BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = in.readLine(); in.close(); @@ -127,54 +136,57 @@ public class Main { } // write the output to a temporary file first. - File tmpFile = File.createTempFile("hudson","log"); + File tmpFile = File.createTempFile("hudson", "log"); try { FileOutputStream os = new FileOutputStream(tmpFile); - Writer w = new OutputStreamWriter(os,"UTF-8"); + Writer w = new OutputStreamWriter(os, "UTF-8"); w.write("<?xml version='1.0' encoding='UTF-8'?>"); - w.write("<run><log encoding='hexBinary' content-encoding='"+Charset.defaultCharset().name()+"'>"); + w.write("<run><log encoding='hexBinary' content-encoding='" + Charset.defaultCharset().name() + "'>"); w.flush(); // run the command long start = System.currentTimeMillis(); List<String> cmd = new ArrayList<String>(); - for( int i=1; i<args.length; i++ ) + for (int i = 1; i < args.length; i++) { cmd.add(args[i]); - Proc proc = new Proc.LocalProc(cmd.toArray(new String[cmd.size()]),(String[])null,System.in, - new DualOutputStream(System.out,new EncodingStream(os))); + } + Proc proc = new Proc.LocalProc(cmd.toArray(new String[cmd.size()]), (String[]) null, System.in, + new DualOutputStream(System.out, new EncodingStream(os))); int ret = proc.join(); - w.write("</log><result>"+ret+"</result><duration>"+(System.currentTimeMillis()-start)+"</duration></run>"); + w.write("</log><result>" + ret + "</result><duration>" + (System.currentTimeMillis() - start) + "</duration></run>"); w.close(); - String location = home+"job/"+projectNameEnc+"/postBuildResult"; - while(true) { + String location = home + "job/" + projectNameEnc + "/postBuildResult"; + while (true) { try { // start a remote connection HttpURLConnection con = open(new URL(location)); - if (auth != null) con.setRequestProperty("Authorization", auth); + if (auth != null) { + con.setRequestProperty("Authorization", auth); + } if (crumbField != null && crumbValue != null) { con.setRequestProperty(crumbField, crumbValue); } con.setDoOutput(true); // this tells HttpURLConnection not to buffer the whole thing - con.setFixedLengthStreamingMode((int)tmpFile.length()); + con.setFixedLengthStreamingMode((int) tmpFile.length()); con.connect(); // send the data FileInputStream in = new FileInputStream(tmpFile); - Util.copyStream(in,con.getOutputStream()); + Util.copyStream(in, con.getOutputStream()); in.close(); - if(con.getResponseCode()!=200) { - Util.copyStream(con.getErrorStream(),System.err); + if (con.getResponseCode() != 200) { + Util.copyStream(con.getErrorStream(), System.err); } return ret; } catch (HttpRetryException e) { - if(e.getLocation()!=null) { + if (e.getLocation() != null) { // retry with the new location location = e.getLocation(); continue; @@ -189,27 +201,26 @@ public class Main { } /** - * Connects to the given HTTP URL and configure time out, to avoid infinite hang. + * Connects to the given HTTP URL and configure time out, to avoid infinite + * hang. */ private static HttpURLConnection open(URL url) throws IOException { - HttpURLConnection c = (HttpURLConnection)url.openConnection(); + HttpURLConnection c = (HttpURLConnection) url.openConnection(); c.setReadTimeout(TIMEOUT); c.setConnectTimeout(TIMEOUT); return c; } - /** * Set to true if we are running unit tests. */ public static boolean isUnitTest = false; - /** - * Set to true if we are running inside "mvn hpi:run" or "mvn hudson-dev:run" + * Set to true if we are running inside "mvn hpi:run" or "mvn + * hudson-dev:run" */ - public static boolean isDevelopmentMode = Boolean.getBoolean(Main.class.getName()+".development"); - + public static boolean isDevelopmentMode = Boolean.getBoolean(Main.class.getName() + ".development"); /** * Time out for socket connection to Hudson. */ - public static final int TIMEOUT = Integer.getInteger(Main.class.getName()+".timeout",15000); + public static final int TIMEOUT = Integer.getInteger(Main.class.getName() + ".timeout", 15000); } diff --git a/hudson-core/src/main/java/hudson/MarkupText.java b/hudson-core/src/main/java/hudson/MarkupText.java index ae2dd72..c6bc9d1 100644 --- a/hudson-core/src/main/java/hudson/MarkupText.java +++ b/hudson-core/src/main/java/hudson/MarkupText.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi - * + * * *******************************************************************************/ @@ -25,17 +25,16 @@ import java.util.regex.Pattern; /** * Mutable representation of string with HTML mark up. * - * <p> - * This class is used to put mark up on plain text. - * See <a href="https://github.com/hudson/hudson/blob/master/hudson-core/src/test/java/hudson/MarkupTextTest.java"> + * <p> This class is used to put mark up on plain text. See <a + * href="https://github.com/hudson/hudson/blob/master/hudson-core/src/test/java/hudson/MarkupTextTest.java"> * the test code</a> for a typical usage and its result. * * @author Kohsuke Kawaguchi * @since 1.70 */ public class MarkupText extends AbstractMarkupText { - private final String text; + private final String text; /** * Added mark up tags. */ @@ -45,21 +44,21 @@ public class MarkupText extends AbstractMarkupText { * Represents one mark up inserted into text. */ private static final class Tag implements Comparable<Tag> { + /** - * Char position of this tag in {@link MarkupText#text}. - * This tag is placed in front of the character of this index. + * Char position of this tag in {@link MarkupText#text}. This tag is + * placed in front of the character of this index. */ private final int pos; private final String markup; - public Tag(int pos, String markup) { this.pos = pos; this.markup = markup; } public int compareTo(Tag that) { - return this.pos-that.pos; + return this.pos - that.pos; } } @@ -67,18 +66,19 @@ public class MarkupText extends AbstractMarkupText { * Represents a substring of a {@link MarkupText}. */ public final class SubText extends AbstractMarkupText { - private final int start,end; + + private final int start, end; private final int[] groups; public SubText(Matcher m, int textOffset) { start = m.start() + textOffset; - end = m.end() + textOffset; + end = m.end() + textOffset; int cnt = m.groupCount(); - groups = new int[cnt*2]; - for( int i=0; i<cnt; i++ ) { - groups[i*2 ] = m.start(i+1) + textOffset; - groups[i*2+1] = m.end(i+1) + textOffset; + groups = new int[cnt * 2]; + for (int i = 0; i < cnt; i++) { + groups[i * 2] = m.start(i + 1) + textOffset; + groups[i * 2 + 1] = m.end(i + 1) + textOffset; } } @@ -90,76 +90,82 @@ public class MarkupText extends AbstractMarkupText { @Override public SubText subText(int start, int end) { - return MarkupText.this.subText(this.start+start, - end<0 ? this.end+1+end : this.start+end); + return MarkupText.this.subText(this.start + start, + end < 0 ? this.end + 1 + end : this.start + end); } @Override public String getText() { - return text.substring(start,end); + return text.substring(start, end); } @Override public void addMarkup(int startPos, int endPos, String startTag, String endTag) { - MarkupText.this.addMarkup(startPos+start, endPos+start, startTag, endTag); + MarkupText.this.addMarkup(startPos + start, endPos + start, startTag, endTag); } /** * Surrounds this subtext with the specified start tag and the end tag. * - * <p> - * Start/end tag text can contain special tokens "$0", "$1", ... - * and they will be replaced by their {@link #group(int) group match}. - * "\$" can be used to escape characters. + * <p> Start/end tag text can contain special tokens "$0", "$1", ... and + * they will be replaced by their {@link #group(int) group match}. "\$" + * can be used to escape characters. */ public void surroundWith(String startTag, String endTag) { - addMarkup(0,length(),replace(startTag),replace(endTag)); + addMarkup(0, length(), replace(startTag), replace(endTag)); } /** - * Works like {@link #surroundWith(String, String)} except - * that the token replacement is not performed on parameters. + * Works like {@link #surroundWith(String, String)} except that the + * token replacement is not performed on parameters. */ public void surroundWithLiteral(String startTag, String endTag) { - addMarkup(0,length(),startTag,endTag); + addMarkup(0, length(), startTag, endTag); } /** - * Surrounds this subtext with <a>...</a>. + * Surrounds this subtext with <a>...</a>. */ public void href(String url) { - addHyperlink(0,length(),url); + addHyperlink(0, length(), url); } /** - * Gets the start index of the captured group within {@link MarkupText#getText()}. + * Gets the start index of the captured group within + * {@link MarkupText#getText()}. * - * @param groupIndex - * 0 means the start of the whole subtext. 1, 2, ... are - * groups captured by '(...)' in the regexp. + * @param groupIndex 0 means the start of the whole subtext. 1, 2, ... + * are groups captured by '(...)' in the regexp. */ public int start(int groupIndex) { - if(groupIndex==0) return start; - return groups[groupIndex*2-2]; + if (groupIndex == 0) { + return start; + } + return groups[groupIndex * 2 - 2]; } /** - * Gets the start index of this subtext within {@link MarkupText#getText()}. + * Gets the start index of this subtext within + * {@link MarkupText#getText()}. */ public int start() { return start; } /** - * Gets the end index of the captured group within {@link MarkupText#getText()}. + * Gets the end index of the captured group within + * {@link MarkupText#getText()}. */ public int end(int groupIndex) { - if(groupIndex==0) return end; - return groups[groupIndex*2-1]; + if (groupIndex == 0) { + return end; + } + return groups[groupIndex * 2 - 1]; } /** - * Gets the end index of this subtext within {@link MarkupText#getText()}. + * Gets the end index of this subtext within + * {@link MarkupText#getText()}. */ public int end() { return end; @@ -169,13 +175,15 @@ public class MarkupText extends AbstractMarkupText { * Gets the text that represents the captured group. */ public String group(int groupIndex) { - if(start(groupIndex)==-1) + if (start(groupIndex) == -1) { return null; - return text.substring(start(groupIndex),end(groupIndex)); + } + return text.substring(start(groupIndex), end(groupIndex)); } /** * How many captured groups are in this subtext. + * * @since 1.357 */ public int groupCount() { @@ -183,12 +191,13 @@ public class MarkupText extends AbstractMarkupText { } /** - * Replaces the group tokens like "$0", "$1", and etc with their actual matches. + * Replaces the group tokens like "$0", "$1", and etc with their actual + * matches. */ public String replace(String s) { StringBuffer buf = new StringBuffer(); - for( int i=0; i<s.length(); i++) { + for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch == '\\') {// escape char i++; @@ -200,12 +209,13 @@ public class MarkupText extends AbstractMarkupText { // get the group number int groupId = ch - '0'; if (groupId < 0 || groupId > 9) { - buf.append('$').append(ch); + buf.append('$').append(ch); } else { - // add the group text - String group = group(groupId); - if (group != null) - buf.append(group); + // add the group text + String group = group(groupId); + if (group != null) { + buf.append(group); + } } } else { @@ -219,14 +229,14 @@ public class MarkupText extends AbstractMarkupText { @Override protected SubText createSubText(Matcher m) { - return new SubText(m,start); + return new SubText(m, start); } } /** * - * @param text - * Plain text. This shouldn't include any markup nor escape. Those are done later in {@link #toString(boolean)}. + * @param text Plain text. This shouldn't include any markup nor escape. + * Those are done later in {@link #toString(boolean)}. */ public MarkupText(String text) { this.text = text; @@ -240,41 +250,44 @@ public class MarkupText extends AbstractMarkupText { /** * Returns a subtext. * - * @param end - * If negative, -N means "trim the last N-1 chars". That is, (s,-1) is the same as (s,length) + * @param end If negative, -N means "trim the last N-1 chars". That is, + * (s,-1) is the same as (s,length) */ public SubText subText(int start, int end) { - return new SubText(start, end<0 ? text.length()+1+end : end); + return new SubText(start, end < 0 ? text.length() + 1 + end : end); } @Override - public void addMarkup( int startPos, int endPos, String startTag, String endTag ) { + public void addMarkup(int startPos, int endPos, String startTag, String endTag) { rangeCheck(startPos); rangeCheck(endPos); - if(startPos>endPos) throw new IndexOutOfBoundsException(); + if (startPos > endPos) { + throw new IndexOutOfBoundsException(); + } // when multiple tags are added to the same range, we want them to show up like // <b><i>abc</i></b>, not <b><i>abc</b></i>. Also, we'd like <b>abc</b><i>def</i>, // not <b>abc<i></b>def</i>. Do this by inserting them to different places. tags.add(new Tag(startPos, startTag)); - tags.add(0,new Tag(endPos,endTag)); + tags.add(0, new Tag(endPos, endTag)); } public void addMarkup(int pos, String tag) { rangeCheck(pos); - tags.add(new Tag(pos,tag)); + tags.add(new Tag(pos, tag)); } private void rangeCheck(int pos) { - if(pos<0 || pos>text.length()) + if (pos < 0 || pos > text.length()) { throw new IndexOutOfBoundsException(); + } } /** * Returns the fully marked-up text. * - * @deprecated as of 1.350. - * Use {@link #toString(boolean)} to be explicit about the escape mode. + * @deprecated as of 1.350. Use {@link #toString(boolean)} to be explicit + * about the escape mode. */ @Override public String toString() { @@ -284,28 +297,28 @@ public class MarkupText extends AbstractMarkupText { /** * Returns the fully marked-up text. * - * @param preEscape - * If true, the escaping is for the <PRE> context. This leave SP and CR/LF intact. - * If false, the escape is for the normal HTML, thus SP becomes &nbsp; and CR/LF becomes <BR> + * @param preEscape If true, the escaping is for the <PRE> context. This + * leave SP and CR/LF intact. If false, the escape is for the normal HTML, + * thus SP becomes &nbsp; and CR/LF becomes <BR> */ public String toString(boolean preEscape) { - if(tags.isEmpty()) - return preEscape? Util.xmlEscape(text) : Util.escape(text); // the most common case - + if (tags.isEmpty()) { + return preEscape ? Util.xmlEscape(text) : Util.escape(text); // the most common case + } Collections.sort(tags); StringBuilder buf = new StringBuilder(); int copied = 0; // # of chars already copied from text to buf for (Tag tag : tags) { - if (copied<tag.pos) { + if (copied < tag.pos) { String portion = text.substring(copied, tag.pos); buf.append(preEscape ? Util.xmlEscape(portion) : Util.escape(portion)); copied = tag.pos; } buf.append(tag.markup); } - if (copied<text.length()) { + if (copied < text.length()) { String portion = text.substring(copied, text.length()); buf.append(preEscape ? Util.xmlEscape(portion) : Util.escape(portion)); } @@ -322,6 +335,6 @@ public class MarkupText extends AbstractMarkupText { @Override protected SubText createSubText(Matcher m) { - return new SubText(m,0); + return new SubText(m, 0); } } diff --git a/hudson-core/src/main/java/hudson/PermalinkList.java b/hudson-core/src/main/java/hudson/PermalinkList.java index 3f99e59..ed1166f 100644 --- a/hudson-core/src/main/java/hudson/PermalinkList.java +++ b/hudson-core/src/main/java/hudson/PermalinkList.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -30,6 +30,7 @@ import java.util.List; * @since 1.255 */ public final class PermalinkList extends ArrayList<Permalink> { + public PermalinkList(Collection<? extends Permalink> c) { super(c); } @@ -43,9 +44,11 @@ public final class PermalinkList extends ArrayList<Permalink> { * @return null if not found */ public Permalink get(String id) { - for (Permalink p : this) - if(p.getId().equals(id)) + for (Permalink p : this) { + if (p.getId().equals(id)) { return p; + } + } return null; } @@ -54,10 +57,13 @@ public final class PermalinkList extends ArrayList<Permalink> { */ public Permalink findNearest(String id) { List<String> ids = new ArrayList<String>(); - for (Permalink p : this) + for (Permalink p : this) { ids.add(p.getId()); + } String nearest = EditDistance.findNearest(id, ids); - if(nearest==null) return null; + if (nearest == null) { + return null; + } return get(nearest); } } diff --git a/hudson-core/src/main/java/hudson/Platform.java b/hudson-core/src/main/java/hudson/Platform.java index 5ef02be..51ed5a9 100644 --- a/hudson-core/src/main/java/hudson/Platform.java +++ b/hudson-core/src/main/java/hudson/Platform.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -21,17 +21,17 @@ import java.io.File; /** * Strategy object that absorbs the platform differences. * - * <p> - * Do not switch/case on this enum, or do a comparison, as we may add new constants. + * <p> Do not switch/case on this enum, or do a comparison, as we may add new + * constants. * * @author Kohsuke Kawaguchi */ public enum Platform { - WINDOWS(';'),UNIX(':'); + WINDOWS(';'), UNIX(':'); /** - * The character that separates paths in environment variables like PATH and CLASSPATH. - * On Windows ';' and on Unix ':'. + * The character that separates paths in environment variables like PATH and + * CLASSPATH. On Windows ';' and on Unix ':'. * * @see File#pathSeparator */ @@ -42,7 +42,9 @@ public enum Platform { } public static Platform current() { - if(File.pathSeparatorChar==':') return UNIX; + if (File.pathSeparatorChar == ':') { + return UNIX; + } return WINDOWS; } } diff --git a/hudson-core/src/main/java/hudson/Plugin.java b/hudson-core/src/main/java/hudson/Plugin.java index bfa3748..ef92506 100644 --- a/hudson-core/src/main/java/hudson/Plugin.java +++ b/hudson-core/src/main/java/hudson/Plugin.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -38,27 +38,23 @@ import com.thoughtworks.xstream.XStream; /** * Base class of Hudson plugin. * - * <p> - * A plugin needs to derive from this class. + * <p> A plugin needs to derive from this class. * - * <p> - * One instance of a plugin is created by Hudson, and used as the entry point - * to plugin functionality. + * <p> One instance of a plugin is created by Hudson, and used as the entry + * point to plugin functionality. * - * <p> - * A plugin is bound to URL space of Hudson as <tt>${rootURL}/plugin/foo/</tt>, - * where "foo" is taken from your plugin name "foo.hpi". All your web resources - * in src/main/webapp are visible from this URL, and you can also define Jelly - * views against your Plugin class, and those are visible in this URL, too. + * <p> A plugin is bound to URL space of Hudson as + * <tt>${rootURL}/plugin/foo/</tt>, where "foo" is taken from your plugin name + * "foo.hpi". All your web resources in src/main/webapp are visible from this + * URL, and you can also define Jelly views against your Plugin class, and those + * are visible in this URL, too. * - * <p> - * {@link Plugin} can have an optional <tt>config.jelly</tt> page. If present, - * it will become a part of the system configuration page (http://server/hudson/configure). - * This is convenient for exposing/maintaining configuration that doesn't - * fit any {@link Descriptor}s. + * <p> {@link Plugin} can have an optional <tt>config.jelly</tt> page. If + * present, it will become a part of the system configuration page + * (http://server/hudson/configure). This is convenient for exposing/maintaining + * configuration that doesn't fit any {@link Descriptor}s. * - * <p> - * Up until Hudson 1.150 or something, subclasses of {@link Plugin} required + * <p> Up until Hudson 1.150 or something, subclasses of {@link Plugin} required * <tt>@plugin</tt> javadoc annotation, but that is no longer a requirement. * * @author Kohsuke Kawaguchi @@ -67,21 +63,19 @@ import com.thoughtworks.xstream.XStream; public abstract class Plugin implements Saveable { /** - * Set by the {@link PluginManager}. - * This points to the {@link PluginWrapper} that wraps - * this {@link Plugin} object. + * Set by the {@link PluginManager}. This points to the + * {@link PluginWrapper} that wraps this {@link Plugin} object. */ /*package*/ transient PluginWrapper wrapper; /** - * Called when a plugin is loaded to make the {@link ServletContext} object available to a plugin. - * This object allows plugins to talk to the surrounding environment. + * Called when a plugin is loaded to make the {@link ServletContext} object + * available to a plugin. This object allows plugins to talk to the + * surrounding environment. * - * <p> - * The default implementation is no-op. + * <p> The default implementation is no-op. * - * @param context - * Always non-null. + * @param context Always non-null. * * @since 1.42 */ @@ -91,20 +85,20 @@ public abstract class Plugin implements Saveable { /** * Called to allow plugins to initialize themselves. * - * <p> - * This method is called after {@link #setServletContext(ServletContext)} is invoked. - * You can also use {@link Hudson#getInstance()} to access the singleton hudson instance, - * although the plugin start up happens relatively early in the initialization - * stage and not all the data are loaded in Hudson. + * <p> This method is called after + * {@link #setServletContext(ServletContext)} is invoked. You can also use + * {@link Hudson#getInstance()} to access the singleton hudson instance, + * although the plugin start up happens relatively early in the + * initialization stage and not all the data are loaded in Hudson. * - * <p> - * If a plugin wants to run an initialization step after all plugins and extension points - * are registered, a good place to do that is {@link #postInitialize()}. - * If a plugin wants to run an initialization step after all the jobs are loaded, - * {@link ItemListener#onLoaded()} is a good place. + * <p> If a plugin wants to run an initialization step after all plugins and + * extension points are registered, a good place to do that is + * {@link #postInitialize()}. If a plugin wants to run an initialization + * step after all the jobs are loaded, {@link ItemListener#onLoaded()} is a + * good place. * - * @throws Exception - * any exception thrown by the plugin during the initialization will disable plugin. + * @throws Exception any exception thrown by the plugin during the + * initialization will disable plugin. * * @since 1.42 * @see ExtensionPoint @@ -116,23 +110,23 @@ public abstract class Plugin implements Saveable { /** * Called after {@link #start()} is called for all the plugins. * - * @throws Exception - * any exception thrown by the plugin during the initialization will disable plugin. + * @throws Exception any exception thrown by the plugin during the + * initialization will disable plugin. */ - public void postInitialize() throws Exception {} + public void postInitialize() throws Exception { + } /** * Called to orderly shut down Hudson. * - * <p> - * This is a good opportunity to clean up resources that plugin started. - * This method will not be invoked if the {@link #start()} failed abnormally. + * <p> This is a good opportunity to clean up resources that plugin started. + * This method will not be invoked if the {@link #start()} failed + * abnormally. * - * @throws Exception - * if any exception is thrown, it is simply recorded and shut-down of other - * plugins continue. This is primarily just a convenience feature, so that - * each plugin author doesn't have to worry about catching an exception and - * recording it. + * @throws Exception if any exception is thrown, it is simply recorded and + * shut-down of other plugins continue. This is primarily just a convenience + * feature, so that each plugin author doesn't have to worry about catching + * an exception and recording it. * * @since 1.42 */ @@ -141,7 +135,8 @@ public abstract class Plugin implements Saveable { /** * @since 1.233 - * @deprecated as of 1.305 override {@link #configure(StaplerRequest,JSONObject)} instead + * @deprecated as of 1.305 override + * {@link #configure(StaplerRequest,JSONObject)} instead */ public void configure(JSONObject formData) throws IOException, ServletException, FormException { } @@ -149,12 +144,11 @@ public abstract class Plugin implements Saveable { /** * Handles the submission for the system configuration. * - * <p> - * If this class defines <tt>config.jelly</tt> view, be sure to - * override this method and persists the submitted values accordingly. + * <p> If this class defines <tt>config.jelly</tt> view, be sure to override + * this method and persists the submitted values accordingly. * - * <p> - * The following is a sample <tt>config.jelly</tt> that you can start yours with: + * <p> The following is a sample <tt>config.jelly</tt> that you can start + * yours with: * <pre><xmp> * <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> * <f:section title="Locale"> @@ -165,12 +159,12 @@ public abstract class Plugin implements Saveable { * </j:jelly> * </xmp></pre> * - * <p> - * This allows you to access data as {@code formData.getString("systemLocale")} + * <p> This allows you to access data as + * {@code formData.getString("systemLocale")} + * + * <p> If you are using this method, you'll likely be interested in using + * {@link #save()} and {@link #load()}. * - * <p> - * If you are using this method, you'll likely be interested in - * using {@link #save()} and {@link #load()}. * @since 1.305 */ public void configure(StaplerRequest req, JSONObject formData) throws IOException, ServletException, FormException { @@ -178,22 +172,24 @@ public abstract class Plugin implements Saveable { } /** - * This method serves static resources in the plugin under <tt>hudson/plugin/SHORTNAME</tt>. + * This method serves static resources in the plugin under + * <tt>hudson/plugin/SHORTNAME</tt>. */ public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String path = req.getRestOfPath(); - if(path.length()==0) + if (path.length() == 0) { path = "/"; + } - if(path.indexOf("..")!=-1 || path.length()<1) { + if (path.indexOf("..") != -1 || path.length() < 1) { // don't serve anything other than files in the sub directory. rsp.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } // use serveLocalizedFile to support automatic locale selection - rsp.serveLocalizedFile(req, new URL(wrapper.baseResourceURL,'.'+path)); + rsp.serveLocalizedFile(req, new URL(wrapper.baseResourceURL, '.' + path)); } // @@ -202,15 +198,15 @@ public abstract class Plugin implements Saveable { /** * Loads serializable fields of this instance from the persisted storage. * - * <p> - * If there was no previously persisted state, this method is no-op. + * <p> If there was no previously persisted state, this method is no-op. * * @since 1.245 */ protected void load() throws IOException { XmlFile xml = getConfigXml(); - if(xml.exists()) + if (xml.exists()) { xml.unmarshal(this); + } } /** @@ -219,31 +215,33 @@ public abstract class Plugin implements Saveable { * @since 1.245 */ public void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) { + return; + } getConfigXml().write(this); SaveableListener.fireOnChange(this, getConfigXml()); } /** - * Controls the file where {@link #load()} and {@link #save()} - * persists data. + * Controls the file where {@link #load()} and {@link #save()} persists + * data. * - * This method can be also overriden if the plugin wants to - * use a custom {@link XStream} instance to persist data. + * This method can be also overriden if the plugin wants to use a custom + * {@link XStream} instance to persist data. * * @since 1.245 */ protected XmlFile getConfigXml() { return new XmlFile(Hudson.XSTREAM, - new File(Hudson.getInstance().getRootDir(),wrapper.getShortName()+".xml")); + new File(Hudson.getInstance().getRootDir(), wrapper.getShortName() + ".xml")); } - /** - * Dummy instance of {@link Plugin} to be used when a plugin didn't - * supply one on its own. + * Dummy instance of {@link Plugin} to be used when a plugin didn't supply + * one on its own. * * @since 1.321 */ - public static final class DummyImpl extends Plugin {} + public static final class DummyImpl extends Plugin { + } } diff --git a/hudson-core/src/main/java/hudson/PluginFirstClassLoader.java b/hudson-core/src/main/java/hudson/PluginFirstClassLoader.java index fc379cb..3e2ea6a 100644 --- a/hudson-core/src/main/java/hudson/PluginFirstClassLoader.java +++ b/hudson-core/src/main/java/hudson/PluginFirstClassLoader.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Olivier Lamy - * + * Contributors: + * + * Olivier Lamy + * * *******************************************************************************/ @@ -29,70 +29,63 @@ import java.util.List; import org.apache.tools.ant.AntClassLoader; /** - * classLoader which use first /WEB-INF/lib/*.jar and /WEB-INF/classes before core classLoader - * <b>you must use the pluginFirstClassLoader true in the maven-hpi-plugin</b> + * classLoader which use first /WEB-INF/lib/*.jar and /WEB-INF/classes before + * core classLoader <b>you must use the pluginFirstClassLoader true in the + * maven-hpi-plugin</b> + * * @author olamy * @since 1.371 */ public class PluginFirstClassLoader - extends AntClassLoader - implements Closeable -{ - + extends AntClassLoader + implements Closeable { + private List<URL> urls = new ArrayList<URL>(); - public void addPathFiles( Collection<File> paths ) - throws IOException - { - for ( File f : paths ) - { - urls.add( f.toURI().toURL() ); - addPathFile( f ); + public void addPathFiles(Collection<File> paths) + throws IOException { + for (File f : paths) { + urls.add(f.toURI().toURL()); + addPathFile(f); } } /** - * @return List of jar used by the plugin /WEB-INF/lib/*.jar and classes directory /WEB-INF/classes + * @return List of jar used by the plugin /WEB-INF/lib/*.jar and classes + * directory /WEB-INF/classes */ - public List<URL> getURLs() - { + public List<URL> getURLs() { return urls; } - + public void close() - throws IOException - { + throws IOException { cleanup(); } @Override - protected Enumeration findResources( String arg0, boolean arg1 ) - throws IOException - { - Enumeration enu = super.findResources( arg0, arg1 ); + protected Enumeration findResources(String arg0, boolean arg1) + throws IOException { + Enumeration enu = super.findResources(arg0, arg1); return enu; } @Override - protected Enumeration findResources( String name ) - throws IOException - { - Enumeration enu = super.findResources( name ); + protected Enumeration findResources(String name) + throws IOException { + Enumeration enu = super.findResources(name); return enu; } @Override - public URL getResource( String arg0 ) - { - URL url = super.getResource( arg0 ); + public URL getResource(String arg0) { + URL url = super.getResource(arg0); return url; } @Override - public InputStream getResourceAsStream( String name ) - { - InputStream is = super.getResourceAsStream( name ); + public InputStream getResourceAsStream(String name) { + InputStream is = super.getResourceAsStream(name); return is; - } - + } } diff --git a/hudson-core/src/main/java/hudson/PluginMarkerAPT6.java b/hudson-core/src/main/java/hudson/PluginMarkerAPT6.java index 035a435..278b93c 100644 --- a/hudson-core/src/main/java/hudson/PluginMarkerAPT6.java +++ b/hudson-core/src/main/java/hudson/PluginMarkerAPT6.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi, Anton Kozak - * + * *******************************************************************************/ package hudson; @@ -36,10 +36,11 @@ import java.io.Writer; import java.util.Set; /** - * This is moved from maven-hpi-plugin for annotation processing. - * Discovers the type of {@link Plugin} and generates "META-INF/services/hudson.Plugin". - * It's used for manifest creation (Plugin-Class section) and the plugin loading. - * Custom {@link Plugin} implementation is required for the -plugin initialization, for example XStream aliases, etc + * This is moved from maven-hpi-plugin for annotation processing. Discovers the + * type of {@link Plugin} and generates "META-INF/services/hudson.Plugin". It's + * used for manifest creation (Plugin-Class section) and the plugin loading. + * Custom {@link Plugin} implementation is required for the -plugin + * initialization, for example XStream aliases, etc */ @SupportedSourceVersion(SourceVersion.RELEASE_6) @SupportedAnnotationTypes("*") @@ -54,30 +55,31 @@ public class PluginMarkerAPT6 extends AbstractProcessor { */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - ElementScanner6<Void,Void> scanner = new ElementScanner6<Void, Void>() { - @Override - public Void visitType(TypeElement e, Void aVoid) { - if(!e.getModifiers().contains(Modifier.ABSTRACT)) { - Element sc = processingEnv.getTypeUtils().asElement(e.getSuperclass()); - if (sc!=null && ((TypeElement)sc).getQualifiedName().contentEquals(HUDSON_PLUGIN_QUAFIFIER)) { - try { - write(e); - } catch (IOException x) { - StringWriter sw = new StringWriter(); - x.printStackTrace(new PrintWriter(sw)); - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,sw.toString(),e); - } + ElementScanner6<Void, Void> scanner = new ElementScanner6<Void, Void>() { + @Override + public Void visitType(TypeElement e, Void aVoid) { + if (!e.getModifiers().contains(Modifier.ABSTRACT)) { + Element sc = processingEnv.getTypeUtils().asElement(e.getSuperclass()); + if (sc != null && ((TypeElement) sc).getQualifiedName().contentEquals(HUDSON_PLUGIN_QUAFIFIER)) { + try { + write(e); + } catch (IOException x) { + StringWriter sw = new StringWriter(); + x.printStackTrace(new PrintWriter(sw)); + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, sw.toString(), e); } } - - return super.visitType(e, aVoid); } - }; - for( Element e : roundEnv.getRootElements() ) - scanner.scan(e,null); + return super.visitType(e, aVoid); + } + }; + + for (Element e : roundEnv.getRootElements()) { + scanner.scan(e, null); + } - return false; + return false; } /** @@ -89,7 +91,7 @@ public class PluginMarkerAPT6 extends AbstractProcessor { private void write(TypeElement typeElement) throws IOException { FileObject f = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", META_INF_SERVICES_LOCATION); - Writer w = new OutputStreamWriter(f.openOutputStream(),"UTF-8"); + Writer w = new OutputStreamWriter(f.openOutputStream(), "UTF-8"); try { w.write(typeElement.getQualifiedName().toString()); } finally { diff --git a/hudson-core/src/main/java/hudson/PluginStrategy.java b/hudson-core/src/main/java/hudson/PluginStrategy.java index c11b760..e2e331e 100644 --- a/hudson-core/src/main/java/hudson/PluginStrategy.java +++ b/hudson-core/src/main/java/hudson/PluginStrategy.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, Tom Huybrechts - * + * Contributors: + * + * Kohsuke Kawaguchi, Tom Huybrechts + * * *******************************************************************************/ @@ -25,47 +25,49 @@ import java.util.List; /** * Pluggability point for how to create {@link PluginWrapper}. * - * <p> - * This extension point was added to allow plugins to be loaded into a different environment - * (such as loading it in an existing DI container like Plexus.) A plugin strategy is a singleton - * instance, and as such this feature is primarily meant for OEM. + * <p> This extension point was added to allow plugins to be loaded into a + * different environment (such as loading it in an existing DI container like + * Plexus.) A plugin strategy is a singleton instance, and as such this feature + * is primarily meant for OEM. * - * See {@link PluginManager#createPluginStrategy()} for how this instance is created. + * See {@link PluginManager#createPluginStrategy()} for how this instance is + * created. */ public interface PluginStrategy extends ExtensionPoint { - /** - * Creates a plugin wrapper, which provides a management interface for the plugin - * @param archive - * Either a directory that points to a pre-exploded plugin, or an hpi file, or an hpl file. - */ - public abstract PluginWrapper createPluginWrapper(File archive) - throws IOException; + /** + * Creates a plugin wrapper, which provides a management interface for the + * plugin + * + * @param archive Either a directory that points to a pre-exploded plugin, + * or an hpi file, or an hpl file. + */ + public abstract PluginWrapper createPluginWrapper(File archive) + throws IOException; - /** - * Loads the plugin and starts it. - * - * <p> - * This should be done after all the classloaders are constructed for all - * the plugins, so that dependencies can be properly loaded by plugins. - */ - public abstract void load(PluginWrapper wrapper) throws IOException; + /** + * Loads the plugin and starts it. + * + * <p> This should be done after all the classloaders are constructed for + * all the plugins, so that dependencies can be properly loaded by plugins. + */ + public abstract void load(PluginWrapper wrapper) throws IOException; - /** - * Optionally start services provided by the plugin. Should be called - * when all plugins are loaded. - * - * @param plugin - */ - public abstract void initializeComponents(PluginWrapper plugin); + /** + * Optionally start services provided by the plugin. Should be called when + * all plugins are loaded. + * + * @param plugin + */ + public abstract void initializeComponents(PluginWrapper plugin); - /** - * Find components of the given type using the assigned strategy. - * - * @param type The component type - * @param hudson The Hudson scope - * @return Sequence of components - * @since 1.397 - */ - public abstract <T> List<ExtensionComponent<T>> findComponents(Class<T> type, Hudson hudson); + /** + * Find components of the given type using the assigned strategy. + * + * @param type The component type + * @param hudson The Hudson scope + * @return Sequence of components + * @since 1.397 + */ + public abstract <T> List<ExtensionComponent<T>> findComponents(Class<T> type, Hudson hudson); } diff --git a/hudson-core/src/main/java/hudson/PluginWrapper.java b/hudson-core/src/main/java/hudson/PluginWrapper.java index e24104d..205f2fb 100644 --- a/hudson-core/src/main/java/hudson/PluginWrapper.java +++ b/hudson-core/src/main/java/hudson/PluginWrapper.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi, Yahoo! Inc., Erik Ramfelt, Tom Huybrechts - * + * * *******************************************************************************/ @@ -42,90 +42,73 @@ import java.util.Enumeration; import java.util.jar.JarFile; /** - * Represents a Hudson plug-in and associated control information - * for Hudson to control {@link Plugin}. + * Represents a Hudson plug-in and associated control information for Hudson to + * control {@link Plugin}. * - * <p> - * A plug-in is packaged into a jar file whose extension is <tt>".hpi"</tt>, + * <p> A plug-in is packaged into a jar file whose extension is <tt>".hpi"</tt>, * A plugin needs to have a special manifest entry to identify what it is. * - * <p> - * At the runtime, a plugin has two distinct state axis. - * <ol> - * <li>Enabled/Disabled. If enabled, Hudson is going to use it - * next time Hudson runs. Otherwise the next run will ignore it. - * <li>Activated/Deactivated. If activated, that means Hudson is using - * the plugin in this session. Otherwise it's not. - * </ol> - * <p> - * For example, an activated but disabled plugin is still running but the next - * time it won't. + * <p> At the runtime, a plugin has two distinct state axis. <ol> + * <li>Enabled/Disabled. If enabled, Hudson is going to use it next time Hudson + * runs. Otherwise the next run will ignore it. <li>Activated/Deactivated. If + * activated, that means Hudson is using the plugin in this session. Otherwise + * it's not. </ol> <p> For example, an activated but disabled plugin is still + * running but the next time it won't. * * @author Kohsuke Kawaguchi */ public class PluginWrapper implements Comparable<PluginWrapper> { - + private static final Logger LOGGER = Logger.getLogger(PluginWrapper.class.getName()); - /** * {@link PluginManager} to which this belongs to. */ //TODO: review and check whether we can do it private public final PluginManager parent; - /** - * Plugin manifest. - * Contains description of the plugin. + * Plugin manifest. Contains description of the plugin. */ private final Manifest manifest; - /** - * {@link ClassLoader} for loading classes from this plugin. - * Null if disabled. + * {@link ClassLoader} for loading classes from this plugin. Null if + * disabled. */ //TODO: review and check whether we can do it private public final ClassLoader classLoader; - /** - * Base URL for loading static resources from this plugin. - * Null if disabled. The static resources are mapped under - * <tt>hudson/plugin/SHORTNAME/</tt>. + * Base URL for loading static resources from this plugin. Null if disabled. + * The static resources are mapped under <tt>hudson/plugin/SHORTNAME/</tt>. */ //TODO: review and check whether we can do it private public final URL baseResourceURL; - /** - * Used to control enable/disable setting of the plugin. - * If this file exists, plugin will be disabled. + * Used to control enable/disable setting of the plugin. If this file + * exists, plugin will be disabled. */ private final File disableFile; - /** - * Used to control the unpacking of the bundled plugin. - * If a pin file exists, Hudson assumes that the user wants to pin down a particular version - * of a plugin, and will not try to overwrite it. Otherwise, it'll be overwritten - * by a bundled copy, to ensure consistency across upgrade/downgrade. + * Used to control the unpacking of the bundled plugin. If a pin file + * exists, Hudson assumes that the user wants to pin down a particular + * version of a plugin, and will not try to overwrite it. Otherwise, it'll + * be overwritten by a bundled copy, to ensure consistency across + * upgrade/downgrade. + * * @since 1.325 */ private final File pinFile; - /** - * Short name of the plugin. The artifact Id of the plugin. - * This is also used in the URL within Hudson, so it needs - * to remain stable even when the *.hpi file name is changed - * (like Maven does.) + * Short name of the plugin. The artifact Id of the plugin. This is also + * used in the URL within Hudson, so it needs to remain stable even when the + * *.hpi file name is changed (like Maven does.) */ private final String shortName; - /** - * True if this plugin is activated for this session. - * The snapshot of <tt>disableFile.exists()</tt> as of the start up. + * True if this plugin is activated for this session. The snapshot of + * <tt>disableFile.exists()</tt> as of the start up. */ private final boolean active; - private final List<Dependency> dependencies; private final List<Dependency> optionalDependencies; - /** * Is this plugin bundled in hudson.war? */ @@ -133,6 +116,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { public static final class Dependency { //TODO: review and check whether we can do it private + public final String shortName; public final String version; public final boolean optional; @@ -144,7 +128,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } this.shortName = s.substring(0, idx); this.version = s.substring(idx + 1); - + boolean isOptional = false; String[] osgiProperties = s.split(";"); for (int i = 1; i < osgiProperties.length; i++) { @@ -171,36 +155,33 @@ public class PluginWrapper implements Comparable<PluginWrapper> { @Override public String toString() { return shortName + " (" + version + ")"; - } - } - - /** - * @param archive - * A .hpi archive file jar file, or a .hpl linked plugin. - * @param manifest - * The manifest for the plugin - * @param baseResourceURL - * A URL pointing to the resources for this plugin - * @param classLoader - * a classloader that loads classes from this plugin and its dependencies - * @param disableFile - * if this file exists on startup, the plugin will not be activated - * @param dependencies a list of mandatory dependencies - * @param optionalDependencies a list of optional dependencies - */ - public PluginWrapper(PluginManager parent, File archive, Manifest manifest, URL baseResourceURL, - ClassLoader classLoader, File disableFile, - List<Dependency> dependencies, List<Dependency> optionalDependencies) { + } + } + + /** + * @param archive A .hpi archive file jar file, or a .hpl linked plugin. + * @param manifest The manifest for the plugin + * @param baseResourceURL A URL pointing to the resources for this plugin + * @param classLoader a classloader that loads classes from this plugin and + * its dependencies + * @param disableFile if this file exists on startup, the plugin will not be + * activated + * @param dependencies a list of mandatory dependencies + * @param optionalDependencies a list of optional dependencies + */ + public PluginWrapper(PluginManager parent, File archive, Manifest manifest, URL baseResourceURL, + ClassLoader classLoader, File disableFile, + List<Dependency> dependencies, List<Dependency> optionalDependencies) { this.parent = parent; - this.manifest = manifest; - this.shortName = computeShortName(manifest, archive); - this.baseResourceURL = baseResourceURL; - this.classLoader = classLoader; - this.disableFile = disableFile; + this.manifest = manifest; + this.shortName = computeShortName(manifest, archive); + this.baseResourceURL = baseResourceURL; + this.classLoader = classLoader; + this.disableFile = disableFile; this.pinFile = new File(archive.getPath() + ".pinned"); - this.active = !disableFile.exists(); - this.dependencies = dependencies; - this.optionalDependencies = optionalDependencies; + this.active = !disableFile.exists(); + this.dependencies = dependencies; + this.optionalDependencies = optionalDependencies; } public PluginManager getParent() { @@ -252,7 +233,6 @@ public class PluginWrapper implements Comparable<PluginWrapper> { return getBaseName(archive); } - /** * Gets the "abc" portion from "abc.ext". */ @@ -273,7 +253,6 @@ public class PluginWrapper implements Comparable<PluginWrapper> { return optionalDependencies; } - /** * Returns the short name suitable for URL. */ @@ -290,8 +269,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> { /** * Gets the URL that shows more information about this plugin. - * @return - * null if this information is unavailable. + * + * @return null if this information is unavailable. * @since 1.283 */ public String getUrl() { @@ -352,7 +331,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } /** - * Returns true if the version of this plugin is older than the given version. + * Returns true if the version of this plugin is older than the given + * version. */ public boolean isOlderThan(VersionNumber v) { try { @@ -384,7 +364,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { try { ((Closeable) classLoader).close(); } catch (IOException e) { - LOGGER.log(WARNING, "Failed to shut down classloader",e); + LOGGER.log(WARNING, "Failed to shut down classloader", e); } } } @@ -419,8 +399,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } /** - * If true, the plugin is going to be activated next time - * Hudson runs. + * If true, the plugin is going to be activated next time Hudson runs. */ public boolean isEnabled() { return !disableFile.exists(); @@ -440,11 +419,11 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } /** - * Makes sure that all the dependencies exist, and then accept optional dependencies - * as real dependencies. + * Makes sure that all the dependencies exist, and then accept optional + * dependencies as real dependencies. * - * @throws IOException - * thrown if one or several mandatory dependencies doesn't exists. + * @throws IOException thrown if one or several mandatory dependencies + * doesn't exists. */ /*package*/ void resolvePluginDependencies() throws IOException { List<String> missingDependencies = new ArrayList<String>(); @@ -455,7 +434,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } } if (!missingDependencies.isEmpty()) { - throw new IOException("Dependency "+Util.join(missingDependencies, ", ")+" doesn't exist"); + throw new IOException("Dependency " + Util.join(missingDependencies, ", ") + " doesn't exist"); } // add the optional dependencies that exists for (Dependency d : optionalDependencies) { @@ -466,12 +445,11 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } /** - * If the plugin has {@link #getUpdateInfo() an update}, - * returns the {@link UpdateSite.Plugin} object. + * If the plugin has {@link #getUpdateInfo() an update}, returns the + * {@link UpdateSite.Plugin} object. * - * @return - * This method may return null — for example, - * the user may have installed a plugin locally developed. + * @return This method may return null — for example, the user may + * have installed a plugin locally developed. */ public UpdateSite.Plugin getUpdateInfo() { UpdateCenter uc = Hudson.getInstance().getUpdateCenter(); @@ -481,7 +459,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } return null; } - + /** * returns the {@link UpdateSite.Plugin} object, or null. */ @@ -493,14 +471,13 @@ public class PluginWrapper implements Comparable<PluginWrapper> { /** * Returns true if this plugin has update in the update center. * - * <p> - * This method is conservative in the sense that if the version number is incomprehensible, - * it always returns false. + * <p> This method is conservative in the sense that if the version number + * is incomprehensible, it always returns false. */ public boolean hasUpdate() { return getUpdateInfo() != null; } - + public boolean isPinned() { return pinFile.exists(); } @@ -528,8 +505,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> { } /** - * returns the version of the backed up plugin, - * or null if there's no back up. + * returns the version of the backed up plugin, or null if there's no back + * up. */ public String getBackupVersion() { if (getBackupFile().exists()) { @@ -558,6 +535,7 @@ public class PluginWrapper implements Comparable<PluginWrapper> { // Action methods // // + public HttpResponse doMakeEnabled() throws IOException { Hudson.getInstance().checkPermission(Hudson.ADMINISTER); enable(); @@ -581,5 +559,4 @@ public class PluginWrapper implements Comparable<PluginWrapper> { pinFile.delete(); return HttpResponses.ok(); } - } diff --git a/hudson-core/src/main/java/hudson/Proc.java b/hudson-core/src/main/java/hudson/Proc.java index e660672..4bb228a 100644 --- a/hudson-core/src/main/java/hudson/Proc.java +++ b/hudson-core/src/main/java/hudson/Proc.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -40,13 +40,14 @@ import java.util.logging.Logger; /** * External process wrapper. * - * <p> - * Used for launching, monitoring, waiting for a process. + * <p> Used for launching, monitoring, waiting for a process. * * @author Kohsuke Kawaguchi */ public abstract class Proc { - protected Proc() {} + + protected Proc() { + } /** * Checks if the process is still alive. @@ -56,33 +57,32 @@ public abstract class Proc { /** * Terminates the process. * - * @throws IOException - * if there's an error killing a process - * and a stack trace could help the trouble-shooting. + * @throws IOException if there's an error killing a process and a stack + * trace could help the trouble-shooting. */ public abstract void kill() throws IOException, InterruptedException; /** - * Waits for the completion of the process and until we finish reading everything that the process has produced - * to stdout/stderr. + * Waits for the completion of the process and until we finish reading + * everything that the process has produced to stdout/stderr. * - * <p> - * If the thread is interrupted while waiting for the completion - * of the process, this method terminates the process and - * exits with a non-zero exit code. + * <p> If the thread is interrupted while waiting for the completion of the + * process, this method terminates the process and exits with a non-zero + * exit code. * - * @throws IOException - * if there's an error launching/joining a process - * and a stack trace could help the trouble-shooting. + * @throws IOException if there's an error launching/joining a process and a + * stack trace could help the trouble-shooting. */ public abstract int join() throws IOException, InterruptedException; - private static final ExecutorService executor = Executors.newCachedThreadPool(); + /** * Like {@link #join} but can be given a maximum time to wait. + * * @param timeout number of time units * @param unit unit of time - * @param listener place to send messages if there are problems, incl. timeout + * @param listener place to send messages if there are problems, incl. + * timeout * @return exit code from the process * @throws IOException for the same reasons as {@link #join} * @throws InterruptedException for the same reasons as {@link #join} @@ -96,8 +96,8 @@ public abstract class Proc { public void run() { try { if (!latch.await(timeout, unit)) { - listener.error("Timeout after " + timeout + " " + - unit.toString().toLowerCase(Locale.ENGLISH)); + listener.error("Timeout after " + timeout + " " + + unit.toString().toLowerCase(Locale.ENGLISH)); kill(); } } catch (InterruptedException x) { @@ -114,83 +114,86 @@ public abstract class Proc { latch.countDown(); } } - + /** * Locally launched process. */ public static final class LocalProc extends Proc { + private final Process proc; - private final Thread copier,copier2; + private final Thread copier, copier2; private final OutputStream out; private final EnvVars cookie; private final String name; - public LocalProc(String cmd, Map<String,String> env, OutputStream out, File workDir) throws IOException { - this(cmd,Util.mapToEnv(env),out,workDir); + public LocalProc(String cmd, Map<String, String> env, OutputStream out, File workDir) throws IOException { + this(cmd, Util.mapToEnv(env), out, workDir); } - public LocalProc(String[] cmd, Map<String,String> env,InputStream in, OutputStream out) throws IOException { - this(cmd,Util.mapToEnv(env),in,out); + public LocalProc(String[] cmd, Map<String, String> env, InputStream in, OutputStream out) throws IOException { + this(cmd, Util.mapToEnv(env), in, out); } - public LocalProc(String cmd,String[] env,OutputStream out, File workDir) throws IOException { - this( Util.tokenize(cmd), env, out, workDir ); + public LocalProc(String cmd, String[] env, OutputStream out, File workDir) throws IOException { + this(Util.tokenize(cmd), env, out, workDir); } - public LocalProc(String[] cmd,String[] env,OutputStream out, File workDir) throws IOException { - this(cmd,env,null,out,workDir); + public LocalProc(String[] cmd, String[] env, OutputStream out, File workDir) throws IOException { + this(cmd, env, null, out, workDir); } - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out) throws IOException { - this(cmd,env,in,out,null); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out) throws IOException { + this(cmd, env, in, out, null); } - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out, File workDir) throws IOException { - this(cmd,env,in,out,null,workDir); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out, File workDir) throws IOException { + this(cmd, env, in, out, null, workDir); } /** - * @param err - * null to redirect stderr to stdout. + * @param err null to redirect stderr to stdout. */ - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out,OutputStream err,File workDir) throws IOException { - this( calcName(cmd), - stderr(environment(new ProcessBuilder(cmd),env).directory(workDir),err), - in, out, err ); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out, OutputStream err, File workDir) throws IOException { + this(calcName(cmd), + stderr(environment(new ProcessBuilder(cmd), env).directory(workDir), err), + in, out, err); } private static ProcessBuilder stderr(ProcessBuilder pb, OutputStream stderr) { - if(stderr==null) pb.redirectErrorStream(true); + if (stderr == null) { + pb.redirectErrorStream(true); + } return pb; } private static ProcessBuilder environment(ProcessBuilder pb, String[] env) { - if(env!=null) { + if (env != null) { Map<String, String> m = pb.environment(); m.clear(); for (String e : env) { int idx = e.indexOf('='); - m.put(e.substring(0,idx),e.substring(idx+1,e.length())); + m.put(e.substring(0, idx), e.substring(idx + 1, e.length())); } } return pb; } - private LocalProc( String name, ProcessBuilder procBuilder, InputStream in, OutputStream out, OutputStream err ) throws IOException { + private LocalProc(String name, ProcessBuilder procBuilder, InputStream in, OutputStream out, OutputStream err) throws IOException { Logger.getLogger(Proc.class.getName()).log(Level.FINE, "Running: {0}", name); this.name = name; this.out = out; this.cookie = EnvVars.createCookie(); procBuilder.environment().putAll(cookie); this.proc = procBuilder.start(); - copier = new StreamCopyThread(name+": stdout copier", proc.getInputStream(), out); + copier = new StreamCopyThread(name + ": stdout copier", proc.getInputStream(), out); copier.start(); - if(in!=null) - new StdinCopyThread(name+": stdin copier",in,proc.getOutputStream()).start(); - else + if (in != null) { + new StdinCopyThread(name + ": stdin copier", in, proc.getOutputStream()).start(); + } else { proc.getOutputStream().close(); - if(err!=null) { - copier2 = new StreamCopyThread(name+": stderr copier", proc.getErrorStream(), err); + } + if (err != null) { + copier2 = new StreamCopyThread(name + ": stderr copier", proc.getErrorStream(), err); copier2.start(); } else { // while this is not discussed in javadoc, even with ProcessBuilder.redirectErrorStream(true), @@ -212,7 +215,7 @@ public abstract class Proc { String oldName = t.getName(); if (SHOW_PID) { ProcessTree.OSProcess p = ProcessTree.get().get(proc); - t.setName(oldName+" "+(p!=null?"waiting for pid="+p.getPid():"waiting for "+name)); + t.setName(oldName + " " + (p != null ? "waiting for pid=" + p.getPid() : "waiting for " + name)); } try { @@ -220,14 +223,16 @@ public abstract class Proc { // see http://wiki.hudson-ci.org/display/HUDSON/Spawning+processes+from+build // problems like that shows up as infinite wait in join(), which confuses great many users. // So let's do a timed wait here and try to diagnose the problem - copier.join(10*1000); - if(copier2!=null) copier2.join(10*1000); - if(copier.isAlive() || (copier2!=null && copier2.isAlive())) { + copier.join(10 * 1000); + if (copier2 != null) { + copier2.join(10 * 1000); + } + if (copier.isAlive() || (copier2 != null && copier2.isAlive())) { // looks like handles are leaking. // closing these handles should terminate the threads. String msg = "Process leaked file descriptors. See http://wiki.hudson-ci.org/display/HUDSON/Spawning+processes+from+build for more information"; Throwable e = new Exception().fillInStackTrace(); - LOGGER.log(Level.WARNING,msg,e); + LOGGER.log(Level.WARNING, msg, e); // doing proc.getInputStream().close() hangs in FileInputStream.close0() // it could be either because another thread is blocking on read, or @@ -276,14 +281,15 @@ public abstract class Proc { * Destroys the child process without join. */ private void destroy() throws InterruptedException { - ProcessTree.get().killAll(proc,cookie); + ProcessTree.get().killAll(proc, cookie); } /** - * {@link Process#getOutputStream()} is buffered, so we need to eagerly flash - * the stream to push bytes to the process. + * {@link Process#getOutputStream()} is buffered, so we need to eagerly + * flash the stream to push bytes to the process. */ private static class StdinCopyThread extends Thread { + private final InputStream in; private final OutputStream out; @@ -316,7 +322,9 @@ public abstract class Proc { private static String calcName(String[] cmd) { StringBuilder buf = new StringBuilder(); for (String token : cmd) { - if(buf.length()>0) buf.append(' '); + if (buf.length() > 0) { + buf.append(' '); + } buf.append(token); } return buf.toString(); @@ -327,6 +335,7 @@ public abstract class Proc { * Retemoly launched process via {@link Channel}. */ public static final class RemoteProc extends Proc { + private final Future<Integer> process; public RemoteProc(Future<Integer> process) { @@ -347,9 +356,10 @@ public abstract class Proc { process.cancel(true); throw e; } catch (ExecutionException e) { - if(e.getCause() instanceof IOException) - throw (IOException)e.getCause(); - throw new IOException2("Failed to join the process",e); + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } + throw new IOException2("Failed to join the process", e); } catch (CancellationException x) { return -1; } @@ -360,7 +370,6 @@ public abstract class Proc { return !process.isDone(); } } - private static final Logger LOGGER = Logger.getLogger(Proc.class.getName()); /** * Debug switch to have the thread display the process it's waiting for. diff --git a/hudson-core/src/main/java/hudson/ProxyConfiguration.java b/hudson-core/src/main/java/hudson/ProxyConfiguration.java index 1af0a28..b8ac0c9 100644 --- a/hudson-core/src/main/java/hudson/ProxyConfiguration.java +++ b/hudson-core/src/main/java/hudson/ProxyConfiguration.java @@ -10,7 +10,7 @@ * * Contributors: * -* Kohsuke Kawaguchi, Winston Prakash + * Kohsuke Kawaguchi, Winston Prakash * * ****************************************************************************** @@ -57,7 +57,6 @@ public final class ProxyConfiguration implements Saveable { public String noProxyFor; private int TIME_OUT_RETRY_COUNT = 5; private int CONNECTION_TIME_OUT_MS = 2000; - private transient Logger logger = LoggerFactory.getLogger(ProxyConfiguration.class); /** * Possibly null proxy user name and password. Password is base64 scrambled @@ -66,18 +65,17 @@ public final class ProxyConfiguration implements Saveable { private String userName; private String password; private boolean authNeeded = false; - private File rootDir; - - public ProxyConfiguration(File dir) throws IOException{ + + public ProxyConfiguration(File dir) throws IOException { rootDir = dir; load(); } - + public ProxyConfiguration(String name, int port) { this(name, port, null, null, null, false); } - + public ProxyConfiguration(String name, int port, String noProxyFor, String userName, String password, boolean authNeeded) { configure(name, port, noProxyFor, userName, password, authNeeded); } @@ -99,7 +97,7 @@ public final class ProxyConfiguration implements Saveable { public int getPort() { return port; } - + public String getNoProxyFor() { return noProxyFor; } @@ -148,8 +146,8 @@ public final class ProxyConfiguration implements Saveable { } public URLConnection openUrl(URL url) throws IOException { - - if (name == null){ + + if (name == null) { URLConnection urlConnection = url.openConnection(); connect(urlConnection); return urlConnection; @@ -179,8 +177,8 @@ public final class ProxyConfiguration implements Saveable { connect(urlConnection); return urlConnection; } - - private void connect(URLConnection urlConnection) throws IOException{ + + private void connect(URLConnection urlConnection) throws IOException { boolean connected = false; int count = 0; urlConnection.setConnectTimeout(CONNECTION_TIME_OUT_MS); @@ -207,8 +205,8 @@ public final class ProxyConfiguration implements Saveable { } } - - /** + + /** * This method should be used wherever {@link URL#openConnection()} to * internet URLs is invoked directly. */ @@ -224,7 +222,6 @@ public final class ProxyConfiguration implements Saveable { } } - private static final XStream XSTREAM = new XStream2(); static { diff --git a/hudson-core/src/main/java/hudson/RelativePath.java b/hudson-core/src/main/java/hudson/RelativePath.java index ff7b8d9..f56f414 100644 --- a/hudson-core/src/main/java/hudson/RelativePath.java +++ b/hudson-core/src/main/java/hudson/RelativePath.java @@ -8,7 +8,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * + * * *******************************************************************************/ @@ -24,12 +24,11 @@ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; /** - * Used in conjunction with {@link QueryParameter} to refer to - * nearby parameters that belong to different parents. + * Used in conjunction with {@link QueryParameter} to refer to nearby parameters + * that belong to different parents. * - * <p> - * Currently, "..", "../..", etc. are supported to indicate - * parameters that belong to the ancestors. + * <p> Currently, "..", "../..", etc. are supported to indicate parameters that + * belong to the ancestors. * * @author Kohsuke Kawaguchi * @since 1.376 @@ -38,5 +37,6 @@ import static java.lang.annotation.RetentionPolicy.*; @Target(PARAMETER) @Retention(RUNTIME) public @interface RelativePath { + String value(); } diff --git a/hudson-core/src/main/java/hudson/ResponseHeaderFilter.java b/hudson-core/src/main/java/hudson/ResponseHeaderFilter.java index 96a09b4..57780a6 100644 --- a/hudson-core/src/main/java/hudson/ResponseHeaderFilter.java +++ b/hudson-core/src/main/java/hudson/ResponseHeaderFilter.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, id:digerata - * + * Contributors: + * + * Kohsuke Kawaguchi, id:digerata + * * *******************************************************************************/ @@ -28,20 +28,16 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** - * This filter allows you to modify headers set by the container or other servlets - * that are out of your control. The particular headers you wish to change are configured - * in web.xml. - * <p> - * One particular header you you may wish to deal with is "Cache-Control: no-cache" - * This is a problem with Tomcat when security is used. Continue reading for further details. - * <p> - * If a web app has a <security-constraint> in its web.xml, Tomcat will - * add a Cache-Control header to every file it serves from that location. This - * header will prevent browsers from caching the file locally and this drastically slows - * down Hudson page load times. - * <p> - * To enable this filter, edit the web.xml file to include: - * + * This filter allows you to modify headers set by the container or other + * servlets that are out of your control. The particular headers you wish to + * change are configured in web.xml. <p> One particular header you you may wish + * to deal with is "Cache-Control: no-cache" This is a problem with Tomcat when + * security is used. Continue reading for further details. <p> If a web app has + * a <security-constraint> in its web.xml, Tomcat will add a Cache-Control + * header to every file it serves from that location. This header will prevent + * browsers from caching the file locally and this drastically slows down Hudson + * page load times. <p> To enable this filter, edit the web.xml file to include: + * * <pre> * <filter> * <filter-name>change-headers-filter</filter-name> @@ -55,44 +51,45 @@ import java.io.IOException; * <param-value>max-age=86400, public</param-value> * </init-param> * </filter> - * + * * And down below that: - * + * * <filter-mapping> * <filter-name>Headers</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> * </pre> - * - * <p> - * In the case of the tomcat cache problem, it is important that the url-pattern for - * the filter matches the url-pattern set for the security-constraint. - * + * + * <p> In the case of the tomcat cache problem, it is important that the + * url-pattern for the filter matches the url-pattern set for the + * security-constraint. + * * @author Mike Wille */ public class ResponseHeaderFilter implements Filter { - private FilterConfig config; - public void init(FilterConfig filterConfig) throws ServletException { - config = filterConfig; - } + private FilterConfig config; + + public void init(FilterConfig filterConfig) throws ServletException { + config = filterConfig; + } - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, - ServletException { - HttpServletResponse httpResp = (HttpServletResponse) resp; + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, + ServletException { + HttpServletResponse httpResp = (HttpServletResponse) resp; - Enumeration e = config.getInitParameterNames(); + Enumeration e = config.getInitParameterNames(); - // for each configuration element... - while(e.hasMoreElements()) { - String headerName = (String) e.nextElement(); - String headerValue = config.getInitParameter(headerName); - // set the header with the given name and value - httpResp.setHeader(headerName, headerValue); - } - chain.doFilter(req, resp); - } + // for each configuration element... + while (e.hasMoreElements()) { + String headerName = (String) e.nextElement(); + String headerValue = config.getInitParameter(headerName); + // set the header with the given name and value + httpResp.setHeader(headerName, headerValue); + } + chain.doFilter(req, resp); + } - public void destroy() { - } + public void destroy() { + } } diff --git a/hudson-core/src/main/java/hudson/RestrictedSince.java b/hudson-core/src/main/java/hudson/RestrictedSince.java index 209e3a8..797780d 100644 --- a/hudson-core/src/main/java/hudson/RestrictedSince.java +++ b/hudson-core/src/main/java/hudson/RestrictedSince.java @@ -7,26 +7,27 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * * - * * Kohsuke Kawaguchi * *******************************************************************************/ package hudson; - import java.lang.annotation.Documented; /** - * Accompanies {@link Depricated} annotation to indicate when the access restriction was placed. + * Accompanies {@link Depricated} annotation to indicate when the access + * restriction was placed. * * @author Kohsuke Kawaguchi * @since 1.355 */ @Documented public @interface RestrictedSince { + /** * Hudson version number that this deprecation has started. */ diff --git a/hudson-core/src/main/java/hudson/StructuredForm.java b/hudson-core/src/main/java/hudson/StructuredForm.java index f39947e..e07a7ed 100644 --- a/hudson-core/src/main/java/hudson/StructuredForm.java +++ b/hudson-core/src/main/java/hudson/StructuredForm.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -25,42 +25,44 @@ import java.util.Collections; import java.util.List; /** - * Obtains the structured form data from {@link StaplerRequest}. - * See http://wiki.hudson-ci.org/display/HUDSON/Structured+Form+Submission + * Obtains the structured form data from {@link StaplerRequest}. See + * http://wiki.hudson-ci.org/display/HUDSON/Structured+Form+Submission * * @author Kohsuke Kawaguchi */ public class StructuredForm { /** - * @deprecated - * Use {@link StaplerRequest#getSubmittedForm()}. Since 1.238. + * @deprecated Use {@link StaplerRequest#getSubmittedForm()}. Since 1.238. */ public static JSONObject get(StaplerRequest req) throws ServletException { return req.getSubmittedForm(); } + /** - * Retrieves the property of the given object and returns it as a list of {@link JSONObject}. + * Retrieves the property of the given object and returns it as a list of + * {@link JSONObject}. * - * <p> - * If the value doesn't exist, this method returns an empty list. If the value is - * a {@link JSONObject}, this method will return a singleton list. If it's a {@link JSONArray}, - * the contents will be returned as a list. + * <p> If the value doesn't exist, this method returns an empty list. If the + * value is a {@link JSONObject}, this method will return a singleton list. + * If it's a {@link JSONArray}, the contents will be returned as a list. * - * <p> - * Because of the way structured form submission work, this is convenient way of - * handling repeated multi-value entries. + * <p> Because of the way structured form submission work, this is + * convenient way of handling repeated multi-value entries. * - * @since 1.233 + * @since 1.233 */ public static List<JSONObject> toList(JSONObject parent, String propertyName) { Object v = parent.get(propertyName); - if(v==null) + if (v == null) { return Collections.emptyList(); - if(v instanceof JSONObject) - return Collections.singletonList((JSONObject)v); - if(v instanceof JSONArray) - return (List)(JSONArray)v; + } + if (v instanceof JSONObject) { + return Collections.singletonList((JSONObject) v); + } + if (v instanceof JSONArray) { + return (List) (JSONArray) v; + } throw new IllegalArgumentException(); } diff --git a/hudson-core/src/main/java/hudson/SystemQuietingDownGlobalMessage.java b/hudson-core/src/main/java/hudson/SystemQuietingDownGlobalMessage.java index 9b1c1a4..b353cc2 100644 --- a/hudson-core/src/main/java/hudson/SystemQuietingDownGlobalMessage.java +++ b/hudson-core/src/main/java/hudson/SystemQuietingDownGlobalMessage.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -24,7 +24,6 @@ import hudson.model.Hudson; * @author <a href="mailto:jason@planet57.com">Jason Dillon</a> * @since 2.1.0 */ - @Extension(ordinal = Integer.MAX_VALUE) public class SystemQuietingDownGlobalMessage extends GlobalMessage { diff --git a/hudson-core/src/main/java/hudson/TcpSlaveAgentListener.java b/hudson-core/src/main/java/hudson/TcpSlaveAgentListener.java index 28ffded..56f68ad 100644 --- a/hudson-core/src/main/java/hudson/TcpSlaveAgentListener.java +++ b/hudson-core/src/main/java/hudson/TcpSlaveAgentListener.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi, Stephen Connolly - * + * Contributors: + * + * Kohsuke Kawaguchi, Stephen Connolly + * * *******************************************************************************/ @@ -53,27 +53,21 @@ import hudson.cli.CliEntryPoint; /** * Listens to incoming TCP connections from JNLP slave agents and CLI. * - * <h2>Security</h2> - * <p> - * Once connected, remote slave agents can send in commands to be - * executed on the master, so in a way this is like an rsh service. - * Therefore, it is important that we reject connections from + * <h2>Security</h2> <p> Once connected, remote slave agents can send in + * commands to be executed on the master, so in a way this is like an rsh + * service. Therefore, it is important that we reject connections from * unauthorized remote slaves. * - * <p> - * The approach here is to have {@link Hudson#getSecretKey() a secret key} on the master. - * This key is sent to the slave inside the <tt>.jnlp</tt> file - * (this file itself is protected by HTTP form-based authentication that - * we use everywhere else in Hudson), and the slave sends this - * token back when it connects to the master. - * Unauthorized slaves can't access the protected <tt>.jnlp</tt> file, - * so it can't impersonate a valid slave. + * <p> The approach here is to have {@link Hudson#getSecretKey() a secret key} + * on the master. This key is sent to the slave inside the <tt>.jnlp</tt> file + * (this file itself is protected by HTTP form-based authentication that we use + * everywhere else in Hudson), and the slave sends this token back when it + * connects to the master. Unauthorized slaves can't access the protected + * <tt>.jnlp</tt> file, so it can't impersonate a valid slave. * - * <p> - * We don't want to force the JNLP slave agents to be restarted - * whenever the server restarts, so right now this secret master key - * is generated once and used forever, which makes this whole scheme - * less secure. + * <p> We don't want to force the JNLP slave agents to be restarted whenever the + * server restarts, so right now this secret master key is generated once and + * used forever, which makes this whole scheme less secure. * * @author Kohsuke Kawaguchi */ @@ -81,23 +75,21 @@ public final class TcpSlaveAgentListener extends Thread { private final ServerSocket serverSocket; private volatile boolean shuttingDown; - public final int configuredPort; /** - * @param port - * Use 0 to choose a random port. + * @param port Use 0 to choose a random port. */ public TcpSlaveAgentListener(int port) throws IOException { - super("TCP slave agent listener port="+port); + super("TCP slave agent listener port=" + port); try { serverSocket = new ServerSocket(port); } catch (BindException e) { - throw (BindException)new BindException("Failed to listen on port "+port+" because it's already in use.").initCause(e); + throw (BindException) new BindException("Failed to listen on port " + port + " because it's already in use.").initCause(e); } this.configuredPort = port; - LOGGER.info("JNLP slave agent listener started on TCP port "+getPort()); + LOGGER.info("JNLP slave agent listener started on TCP port " + getPort()); start(); } @@ -128,8 +120,8 @@ public final class TcpSlaveAgentListener extends Thread { new ConnectionHandler(s).start(); } } catch (IOException e) { - if(!shuttingDown) { - LOGGER.log(Level.SEVERE,"Failed to accept JNLP slave agent connections",e); + if (!shuttingDown) { + LOGGER.log(Level.SEVERE, "Failed to accept JNLP slave agent connections", e); } } } @@ -142,11 +134,12 @@ public final class TcpSlaveAgentListener extends Thread { try { serverSocket.close(); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to close down TCP port",e); + LOGGER.log(Level.WARNING, "Failed to close down TCP port", e); } } private final class ConnectionHandler extends Thread { + private final Socket s; /** * Unique number to identify this connection. Used in the log. @@ -155,45 +148,45 @@ public final class TcpSlaveAgentListener extends Thread { public ConnectionHandler(Socket s) { this.s = s; - synchronized(getClass()) { + synchronized (getClass()) { id = iotaGen++; } - setName("TCP slave agent connection handler #"+id+" with "+s.getRemoteSocketAddress()); + setName("TCP slave agent connection handler #" + id + " with " + s.getRemoteSocketAddress()); } @Override public void run() { try { - LOGGER.info("Accepted connection #"+id+" from "+s.getRemoteSocketAddress()); + LOGGER.info("Accepted connection #" + id + " from " + s.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(s.getInputStream()); - PrintWriter out = new PrintWriter(s.getOutputStream(),true); + PrintWriter out = new PrintWriter(s.getOutputStream(), true); String s = in.readUTF(); - if(s.startsWith("Protocol:")) { + if (s.startsWith("Protocol:")) { String protocol = s.substring(9); - if(protocol.equals("JNLP-connect")) { + if (protocol.equals("JNLP-connect")) { runJnlpConnect(in, out); - } else if(protocol.equals("JNLP2-connect")) { + } else if (protocol.equals("JNLP2-connect")) { runJnlp2Connect(in, out); - } else if(protocol.equals("CLI-connect")) { + } else if (protocol.equals("CLI-connect")) { runCliConnect(in, out); } else { error(out, "Unknown protocol:" + s); } } else { - error(out, "Unrecognized protocol: "+s); + error(out, "Unrecognized protocol: " + s); } } catch (InterruptedException e) { - LOGGER.log(Level.WARNING,"Connection #"+id+" aborted",e); + LOGGER.log(Level.WARNING, "Connection #" + id + " aborted", e); try { s.close(); } catch (IOException _) { // try to clean up the socket } } catch (IOException e) { - LOGGER.log(Level.WARNING,"Connection #"+id+" failed",e); + LOGGER.log(Level.WARNING, "Connection #" + id + " failed", e); try { s.close(); } catch (IOException _) { @@ -211,7 +204,7 @@ public final class TcpSlaveAgentListener extends Thread { Computer.threadPoolForRemoting, Mode.BINARY, new BufferedInputStream(new SocketInputStream(this.s)), new BufferedOutputStream(new SocketOutputStream(this.s)), null, true); - channel.setProperty(CliEntryPoint.class.getName(),new CliManagerImpl()); + channel.setProperty(CliEntryPoint.class.getName(), new CliManagerImpl()); channel.join(); } @@ -219,20 +212,20 @@ public final class TcpSlaveAgentListener extends Thread { * Handles JNLP slave agent connection request. */ private void runJnlpConnect(DataInputStream in, PrintWriter out) throws IOException, InterruptedException { - if(!getSecretKey().equals(in.readUTF())) { + if (!getSecretKey().equals(in.readUTF())) { error(out, "Unauthorized access"); return; } final String nodeName = in.readUTF(); SlaveComputer computer = (SlaveComputer) Hudson.getInstance().getComputer(nodeName); - if(computer==null) { - error(out, "No such slave: "+nodeName); + if (computer == null) { + error(out, "No such slave: " + nodeName); return; } - if(computer.getChannel()!=null) { - error(out, nodeName+" is already connected to this master. Rejecting this connection."); + if (computer.getChannel() != null) { + error(out, nodeName + " is already connected to this master. Rejecting this connection."); return; } @@ -248,31 +241,31 @@ public final class TcpSlaveAgentListener extends Thread { Properties request = new Properties(); request.load(new ByteArrayInputStream(in.readUTF().getBytes("UTF-8"))); - if(!getSecretKey().equals(request.getProperty("Secret-Key"))) { + if (!getSecretKey().equals(request.getProperty("Secret-Key"))) { error(out, "Unauthorized access"); return; } final String nodeName = request.getProperty("Node-Name"); SlaveComputer computer = (SlaveComputer) Hudson.getInstance().getComputer(nodeName); - if(computer==null) { - error(out, "No such slave: "+nodeName); + if (computer == null) { + error(out, "No such slave: " + nodeName); return; } Channel ch = computer.getChannel(); - if(ch !=null) { + if (ch != null) { String c = request.getProperty("Cookie"); - if (c!=null && c.equals(ch.getProperty(COOKIE_NAME))) { + if (c != null && c.equals(ch.getProperty(COOKIE_NAME))) { // we think we are currently connected, but this request proves that it's from the party // we are supposed to be communicating to. so let the current one get disconnected - LOGGER.info("Disconnecting "+nodeName+" as we are reconnected from the current peer"); + LOGGER.info("Disconnecting " + nodeName + " as we are reconnected from the current peer"); try { computer.disconnect(new ConnectionFromCurrentPeer()).get(15, TimeUnit.SECONDS); } catch (ExecutionException e) { - throw new IOException2("Failed to disconnect the current client",e); + throw new IOException2("Failed to disconnect the current client", e); } catch (TimeoutException e) { - throw new IOException2("Failed to disconnect the current client",e); + throw new IOException2("Failed to disconnect the current client", e); } } else { error(out, nodeName + " is already connected to this master. Rejecting this connection."); @@ -284,7 +277,7 @@ public final class TcpSlaveAgentListener extends Thread { Properties response = new Properties(); String cookie = generateCookie(); - response.put("Cookie",cookie); + response.put("Cookie", cookie); writeResponseHeaders(out, response); ch = jnlpConnect(computer); @@ -294,7 +287,7 @@ public final class TcpSlaveAgentListener extends Thread { private void writeResponseHeaders(PrintWriter out, Properties response) { for (Entry<Object, Object> e : response.entrySet()) { - out.println(e.getKey()+": "+e.getValue()); + out.println(e.getKey() + ": " + e.getValue()); } out.println(); // empty line to conclude the response header } @@ -308,28 +301,29 @@ public final class TcpSlaveAgentListener extends Thread { private Channel jnlpConnect(SlaveComputer computer) throws InterruptedException, IOException { final String nodeName = computer.getName(); final OutputStream log = computer.openLogFile(); - PrintWriter logw = new PrintWriter(log,true); - logw.println("JNLP agent connected from "+ this.s.getInetAddress()); + PrintWriter logw = new PrintWriter(log, true); + logw.println("JNLP agent connected from " + this.s.getInetAddress()); try { computer.setChannel(new BufferedInputStream(this.s.getInputStream()), new BufferedOutputStream(this.s.getOutputStream()), log, - new Listener() { - @Override - public void onClosed(Channel channel, IOException cause) { - try { - log.close(); - } catch (IOException e) { - e.printStackTrace(); + new Listener() { + @Override + public void onClosed(Channel channel, IOException cause) { + try { + log.close(); + } catch (IOException e) { + e.printStackTrace(); + } + if (cause != null) { + LOGGER.log(Level.WARNING, "Connection #" + id + " for + " + nodeName + " terminated", cause); + } + try { + ConnectionHandler.this.s.close(); + } catch (IOException e) { + // ignore + } } - if(cause!=null) - LOGGER.log(Level.WARNING, "Connection #"+id+" for + " + nodeName + " terminated",cause); - try { - ConnectionHandler.this.s.close(); - } catch (IOException e) { - // ignore - } - } - }); + }); return computer.getChannel(); } catch (AbortException e) { logw.println(e.getMessage()); @@ -344,7 +338,7 @@ public final class TcpSlaveAgentListener extends Thread { private void error(PrintWriter out, String msg) throws IOException { out.println(msg); - LOGGER.log(Level.WARNING,"Connection #"+id+" is aborted: "+msg); + LOGGER.log(Level.WARNING, "Connection #" + id + " is aborted: " + msg); s.close(); } } @@ -353,48 +347,46 @@ public final class TcpSlaveAgentListener extends Thread { * Connection terminated because we are reconnected from the current peer. */ public static class ConnectionFromCurrentPeer extends OfflineCause { + public String toString() { return "The current peer is reconnecting"; } } - - private static int iotaGen=1; - + private static int iotaGen = 1; private static final Logger LOGGER = Logger.getLogger(TcpSlaveAgentListener.class.getName()); - - private static final String COOKIE_NAME = TcpSlaveAgentListener.class.getName()+".cookie"; + private static final String COOKIE_NAME = TcpSlaveAgentListener.class.getName() + ".cookie"; } /* -Pasted from http://today.java.net/pub/a/today/2005/09/01/webstart.html - - Is it unrealistic to try to control access to JWS files? - Is anyone doing this? - -It is not unrealistic, and we are doing it. Create a protected web page -with a download button or link that makes a servlet call. If the user has -already logged in to your website, of course they can go there without -further authentication. The servlet reads the cookies sent by the browser -when the link is activated. It then generates a dynamic JNLP file adding -the authentication cookie and any other required cookies (JSESSIONID, etc.) -via <argument> tags. Write the WebStart application so that it picks up -any required cookies from the argument list, and adds these cookies to its -request headers on subsequent calls to the server. (Note: in the dynamic -JNLP file, do NOT put href= in the opening jnlp tag. If you do, JWS will -try to reload the JNLP from disk and since it's dynamic, it won't be there. -Leave it off and JWS will be happy.) - -When returning the dynamic JNLP, the servlet should invoke setHeader( -"Expires", 0 ) and addDateHeader() twice on the servlet response to set -both "Date" and "Last-Modified" to the current date. This keeps the browser -from using a cached copy of a prior dynamic JNLP obtained from the same URL. - -Note also that the JAR file(s) for the JWS application should not be on -a password-protected path - the launcher won't know about the authentication -cookie. But once the application starts, you can run all its requests -through a protected path requiring the authentication cookie, because -the application gets it from the dynamic JNLP. Just write it so that it -can't do anything useful without going through a protected path or doing -something to present credentials that could only have come from a valid -user. -*/ + Pasted from http://today.java.net/pub/a/today/2005/09/01/webstart.html + + Is it unrealistic to try to control access to JWS files? + Is anyone doing this? + + It is not unrealistic, and we are doing it. Create a protected web page + with a download button or link that makes a servlet call. If the user has + already logged in to your website, of course they can go there without + further authentication. The servlet reads the cookies sent by the browser + when the link is activated. It then generates a dynamic JNLP file adding + the authentication cookie and any other required cookies (JSESSIONID, etc.) + via <argument> tags. Write the WebStart application so that it picks up + any required cookies from the argument list, and adds these cookies to its + request headers on subsequent calls to the server. (Note: in the dynamic + JNLP file, do NOT put href= in the opening jnlp tag. If you do, JWS will + try to reload the JNLP from disk and since it's dynamic, it won't be there. + Leave it off and JWS will be happy.) + + When returning the dynamic JNLP, the servlet should invoke setHeader( + "Expires", 0 ) and addDateHeader() twice on the servlet response to set + both "Date" and "Last-Modified" to the current date. This keeps the browser + from using a cached copy of a prior dynamic JNLP obtained from the same URL. + + Note also that the JAR file(s) for the JWS application should not be on + a password-protected path - the launcher won't know about the authentication + cookie. But once the application starts, you can run all its requests + through a protected path requiring the authentication cookie, because + the application gets it from the dynamic JNLP. Just write it so that it + can't do anything useful without going through a protected path or doing + something to present credentials that could only have come from a valid + user. + */ diff --git a/hudson-core/src/main/java/hudson/UDPBroadcastFragment.java b/hudson-core/src/main/java/hudson/UDPBroadcastFragment.java index 7777e5b..e72a88c 100644 --- a/hudson-core/src/main/java/hudson/UDPBroadcastFragment.java +++ b/hudson-core/src/main/java/hudson/UDPBroadcastFragment.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -23,23 +23,23 @@ import java.net.SocketAddress; /** * Extension point that contributes an XML fragment to the UDP broadcast. * - * <p> - * Put {@link Extension} on your implementation class to have it auto-discovered. - * + * <p> Put {@link Extension} on your implementation class to have it + * auto-discovered. + * * @author Kohsuke Kawaguchi * @since 1.304 * @see UDPBroadcastThread */ public abstract class UDPBroadcastFragment implements ExtensionPoint { + /** * Called to build up a response XML. * - * @param buf - * This is the buffer to write XML to. The implementation of this method - * should write a complete fragment. Because of the packet length restriction - * in UDP (somewhere around 1500 bytes), you cannot send a large amount of information. - * @param sender - * The socket address that sent the discovery packet out. + * @param buf This is the buffer to write XML to. The implementation of this + * method should write a complete fragment. Because of the packet length + * restriction in UDP (somewhere around 1500 bytes), you cannot send a large + * amount of information. + * @param sender The socket address that sent the discovery packet out. */ public abstract void buildFragment(StringBuilder buf, SocketAddress sender); diff --git a/hudson-core/src/main/java/hudson/UDPBroadcastThread.java b/hudson-core/src/main/java/hudson/UDPBroadcastThread.java index aa9baa6..32612a6 100644 --- a/hudson-core/src/main/java/hudson/UDPBroadcastThread.java +++ b/hudson-core/src/main/java/hudson/UDPBroadcastThread.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: + * + * * - * - * * *******************************************************************************/ @@ -31,14 +31,15 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * Monitors a UDP multicast broadcast and respond with the location of the Hudson service. + * Monitors a UDP multicast broadcast and respond with the location of the + * Hudson service. * - * <p> - * Useful for auto-discovery of Hudson in the network. + * <p> Useful for auto-discovery of Hudson in the network. * * @author Kohsuke Kawaguchi */ public class UDPBroadcastThread extends Thread { + private final Hudson hudson; //TODO: review and check whether we can do it private public final OneShotEvent ready = new OneShotEvent(); @@ -46,7 +47,7 @@ public class UDPBroadcastThread extends Thread { private boolean shutdown; public UDPBroadcastThread(Hudson hudson) throws IOException { - super("Hudson UDP "+PORT+" monitoring thread"); + super("Hudson UDP " + PORT + " monitoring thread"); this.hudson = hudson; mcs = new MulticastSocket(PORT); } @@ -61,9 +62,9 @@ public class UDPBroadcastThread extends Thread { mcs.joinGroup(MULTICAST); ready.signal(); - while(true) { + while (true) { byte[] buf = new byte[2048]; - DatagramPacket p = new DatagramPacket(buf,buf.length); + DatagramPacket p = new DatagramPacket(buf, buf.length); mcs.receive(p); SocketAddress sender = p.getSocketAddress(); @@ -72,32 +73,37 @@ public class UDPBroadcastThread extends Thread { TcpSlaveAgentListener tal = hudson.getTcpSlaveAgentListener(); StringBuilder rsp = new StringBuilder("<hudson>"); - tag(rsp,"version",Hudson.VERSION); - tag(rsp,"url",hudson.getRootUrl()); - tag(rsp,"slave-port",tal==null?null:tal.getPort()); + tag(rsp, "version", Hudson.VERSION); + tag(rsp, "url", hudson.getRootUrl()); + tag(rsp, "slave-port", tal == null ? null : tal.getPort()); - for (UDPBroadcastFragment f : UDPBroadcastFragment.all()) - f.buildFragment(rsp,sender); + for (UDPBroadcastFragment f : UDPBroadcastFragment.all()) { + f.buildFragment(rsp, sender); + } rsp.append("</hudson>"); byte[] response = rsp.toString().getBytes("UTF-8"); - mcs.send(new DatagramPacket(response,response.length,sender)); + mcs.send(new DatagramPacket(response, response.length, sender)); } } catch (ClosedByInterruptException e) { // shut down } catch (BindException e) { // if we failed to listen to UDP, just silently abandon it, as a stack trace // makes people unnecessarily concerned, for a feature that currently does no good. - LOGGER.log(Level.WARNING, "Failed to listen to UDP port "+PORT,e); + LOGGER.log(Level.WARNING, "Failed to listen to UDP port " + PORT, e); } catch (IOException e) { - if (shutdown) return; // forcibly closed - LOGGER.log(Level.WARNING, "UDP handling problem",e); + if (shutdown) { + return; // forcibly closed + } + LOGGER.log(Level.WARNING, "UDP handling problem", e); } } private void tag(StringBuilder buf, String tag, Object value) { - if(value==null) return; + if (value == null) { + return; + } buf.append('<').append(tag).append('>').append(value).append("</").append(tag).append('>'); } @@ -106,11 +112,8 @@ public class UDPBroadcastThread extends Thread { mcs.close(); interrupt(); } - - public static final int PORT = Integer.getInteger("hudson.udp",33848); - + public static final int PORT = Integer.getInteger("hudson.udp", 33848); private static final Logger LOGGER = Logger.getLogger(UDPBroadcastThread.class.getName()); - /** * Multicast socket address. */ @@ -118,7 +121,7 @@ public class UDPBroadcastThread extends Thread { static { try { - MULTICAST = InetAddress.getByAddress(new byte[]{(byte)239, (byte)77, (byte)124, (byte)213}); + MULTICAST = InetAddress.getByAddress(new byte[]{(byte) 239, (byte) 77, (byte) 124, (byte) 213}); } catch (UnknownHostException e) { throw new Error(e); } diff --git a/hudson-core/src/main/java/hudson/Util.java b/hudson-core/src/main/java/hudson/Util.java index 4c7831e..dec7369 100644 --- a/hudson-core/src/main/java/hudson/Util.java +++ b/hudson-core/src/main/java/hudson/Util.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: + * Contributors: * * Kohsuke Kawaguchi, Winston Prakash - * + * * *******************************************************************************/ package hudson; @@ -103,6 +103,7 @@ public class Util { /** * Creates a filtered sublist. + * * @since 1.176 */ public static <T> List<T> filter(Iterable<?> base, Class<T> type) { @@ -122,15 +123,16 @@ public class Util { return filter((Iterable) base, type); } /** - * Pattern for capturing variables. Either $xyz or ${xyz}, while ignoring "$$" + * Pattern for capturing variables. Either $xyz or ${xyz}, while ignoring + * "$$" */ private static final Pattern VARIABLE = Pattern.compile("\\$([A-Za-z0-9_]+|\\{[A-Za-z0-9_\\.+]+\\}|\\$)"); /** * Replaces the occurrence of '$key' by <tt>properties.get('key')</tt>. * - * <p> - * Unlike shell, undefined variables are left as-is (this behavior is the same as Ant.) + * <p> Unlike shell, undefined variables are left as-is (this behavior is + * the same as Ant.) * */ public static String replaceMacro(String s, Map<String, String> properties) { @@ -140,8 +142,8 @@ public class Util { /** * Replaces the occurrence of '$key' by <tt>resolver.get('key')</tt>. * - * <p> - * Unlike shell, undefined variables are left as-is (this behavior is the same as Ant.) + * <p> Unlike shell, undefined variables are left as-is (this behavior is + * the same as Ant.) */ public static String replaceMacro(String s, VariableResolver<String> resolver) { if (s == null) { @@ -191,7 +193,7 @@ public class Util { BufferedReader r = null; StringBuilder str = new StringBuilder((int) logfile.length()); - try { + try { r = new BufferedReader(new InputStreamReader(new FileInputStream(logfile), charset)); char[] buf = new char[1024]; int len; @@ -206,11 +208,10 @@ public class Util { } /** - * Deletes the contents of the given directory (but not the directory itself) - * recursively. + * Deletes the contents of the given directory (but not the directory + * itself) recursively. * - * @throws IOException - * if the operation fails. + * @throws IOException if the operation fails. */ public static void deleteContentsRecursive(File file) throws IOException { File[] files = file.listFiles(); @@ -224,6 +225,7 @@ public class Util { /** * Deletes this file (and does not take no for an answer). + * * @param f a file to delete * @throws IOException if it exists but could not be successfully deleted */ @@ -237,17 +239,17 @@ public class Util { // perhaps this file is read-only? makeWritable(f); /* - on Unix both the file and the directory that contains it has to be writable - for a file deletion to be successful. (Confirmed on Solaris 9) + on Unix both the file and the directory that contains it has to be writable + for a file deletion to be successful. (Confirmed on Solaris 9) - $ ls -la - total 6 - dr-xr-sr-x 2 hudson hudson 512 Apr 18 14:41 . - dr-xr-sr-x 3 hudson hudson 512 Apr 17 19:36 .. - -r--r--r-- 1 hudson hudson 469 Apr 17 19:36 manager.xml - -rw-r--r-- 1 hudson hudson 0 Apr 18 14:41 x - $ rm x - rm: x not removed: Permission denied + $ ls -la + total 6 + dr-xr-sr-x 2 hudson hudson 512 Apr 18 14:41 . + dr-xr-sr-x 3 hudson hudson 512 Apr 17 19:36 .. + -r--r--r-- 1 hudson hudson 469 Apr 17 19:36 manager.xml + -rw-r--r-- 1 hudson hudson 0 Apr 18 14:41 x + $ rm x + rm: x not removed: Permission denied */ makeWritable(f.getParentFile()); @@ -338,8 +340,8 @@ public class Util { private static final Pattern errorCodeParser = Pattern.compile(".*CreateProcess.*error=([0-9]+).*"); /** - * On Windows, error messages for IOException aren't very helpful. - * This method generates additional user-friendly error message to the listener + * On Windows, error messages for IOException aren't very helpful. This + * method generates additional user-friendly error message to the listener */ public static void displayIOException(IOException e, TaskListener listener) { String msg = getWin32ErrorMessage(e); @@ -355,8 +357,8 @@ public class Util { /** * Extracts the Win32 error message from {@link Throwable} if possible. * - * @return - * null if there seems to be no error code or if the platform is not Win32. + * @return null if there seems to be no error code or if the platform is not + * Win32. */ public static String getWin32ErrorMessage(Throwable e) { String msg = e.getMessage(); @@ -381,8 +383,7 @@ public class Util { /** * Gets a human readable message for the given Win32 error code. * - * @return - * null if no such message is available. + * @return null if no such message is available. */ public static String getWin32ErrorMessage(int n) { try { @@ -442,9 +443,8 @@ public class Util { /** * Tokenizes the text separated by delimiters. * - * <p> - * In 1.210, this method was changed to handle quotes like Unix shell does. - * Before that, this method just used {@link StringTokenizer}. + * <p> In 1.210, this method was changed to handle quotes like Unix shell + * does. Before that, this method just used {@link StringTokenizer}. * * @since 1.145 * @see QuotedStringTokenizer @@ -458,7 +458,8 @@ public class Util { } /** - * Converts the map format of the environment variables to the K=V format in the array. + * Converts the map format of the environment variables to the K=V format in + * the array. */ public static String[] mapToEnv(Map<String, String> m) { String[] r = new String[m.size()]; @@ -501,10 +502,9 @@ public class Util { /** * Computes MD5 digest of the given input stream. * - * @param source - * The stream will be closed by this method at the end of this method. - * @return - * 32-char wide string + * @param source The stream will be closed by this method at the end of this + * method. + * @return 32-char wide string */ public static String getDigestOf(InputStream source) throws IOException { try { @@ -533,6 +533,7 @@ public class Util { /** * Converts a string into 128-bit AES key. + * * @since 1.308 */ public static SecretKey toAes128Key(String s) { @@ -576,11 +577,11 @@ public class Util { } /** - * Returns a human readable text of the time duration, for example "3 minutes 40 seconds". - * This version should be used for representing a duration of some activity (like build) + * Returns a human readable text of the time duration, for example "3 + * minutes 40 seconds". This version should be used for representing a + * duration of some activity (like build) * - * @param duration - * number of milliseconds. + * @param duration number of milliseconds. */ public static String getTimeSpanString(long duration) { // Break the duration up in to units. @@ -620,13 +621,13 @@ public class Util { } /** - * Create a string representation of a time duration. If the quantity of - * the most significant unit is big (>=10), then we use only that most + * Create a string representation of a time duration. If the quantity of the + * most significant unit is big (>=10), then we use only that most * significant unit in the string representation. If the quantity of the - * most significant unit is small (a single-digit value), then we also - * use a secondary, smaller unit for increased precision. - * So 13 minutes and 43 seconds returns just "13 minutes", but 3 minutes - * and 43 seconds is "3 minutes 43 seconds". + * most significant unit is small (a single-digit value), then we also use a + * secondary, smaller unit for increased precision. So 13 minutes and 43 + * seconds returns just "13 minutes", but 3 minutes and 43 seconds is "3 + * minutes 43 seconds". */ private static String makeTimeSpanString(long bigUnit, String bigLabel, @@ -649,11 +650,10 @@ public class Util { /** * Combines number and unit, with a plural suffix if needed. - * - * @deprecated - * Use individual localization methods instead. - * See {@link Messages#Util_year(Object)} for an example. - * Deprecated since 2009-06-24, remove method after 2009-12-24. + * + * @deprecated Use individual localization methods instead. See + * {@link Messages#Util_year(Object)} for an example. Deprecated since + * 2009-06-24, remove method after 2009-12-24. */ public static String combine(long n, String suffix) { String s = Long.toString(n) + ' ' + suffix; @@ -680,11 +680,10 @@ public class Util { /** * Escapes non-ASCII characters in URL. * - * <p> - * Note that this methods only escapes non-ASCII but leaves other URL-unsafe characters, - * such as '#'. - * {@link #rawEncode(String)} should generally be used instead, though be careful to pass only - * a single path component to that method (it will encode /, but this method does not). + * <p> Note that this methods only escapes non-ASCII but leaves other + * URL-unsafe characters, such as '#'. {@link #rawEncode(String)} should + * generally be used instead, though be careful to pass only a single path + * component to that method (it will encode /, but this method does not). */ public static String encode(String s) { try { @@ -738,12 +737,13 @@ public class Util { } /** - * Encode a single path component for use in an HTTP URL. - * Escapes all non-ASCII, general unsafe (space and "#%<>[\]^`{|}~) - * and HTTP special characters (/;:?) as specified in RFC1738. - * (so alphanumeric and !@$&*()-_=+',. are not encoded) - * Note that slash(/) is encoded, so the given string should be a - * single path component used in constructing a URL. + * Encode a single path component for use in an HTTP URL. Escapes all + * non-ASCII, general unsafe (space and "#%<>[\]^`{|}~) and HTTP special + * characters (/;:?) as specified in RFC1738. (so alphanumeric and ! + * + * @$&*()-_=+',. are not encoded) Note that slash(/) is encoded, so the + * given string should be a single path component used in constructing a + * URL. */ public static String rawEncode(String s) { boolean escaped = false; @@ -793,7 +793,8 @@ public class Util { } /** - * Escapes HTML unsafe characters like <, & to the respective character entities. + * Escapes HTML unsafe characters like <, & to the respective + * character entities. */ public static String escape(String text) { if (text == null) { @@ -842,8 +843,8 @@ public class Util { } /** - * Methods acts as {@link #xmlEscape(String)} method with only difference that it also escapes - * '\n', '\r' symbols + * Methods acts as {@link #xmlEscape(String)} method with only difference + * that it also escapes '\n', '\r' symbols * * @param text string to escape * @return escaped string. @@ -990,18 +991,16 @@ public class Util { /** * Creates Ant {@link FileSet} with the base dir and include pattern. * - * <p> - * The difference with this and using {@link FileSet#setIncludes(String)} - * is that this method doesn't treat whitespace as a pattern separator, - * which makes it impossible to use space in the file path. + * <p> The difference with this and using + * {@link FileSet#setIncludes(String)} is that this method doesn't treat + * whitespace as a pattern separator, which makes it impossible to use space + * in the file path. * - * @param includes - * String like "foo/bar/*.xml" Multiple patterns can be separated - * by ',', and whitespace can surround ',' (so that you can write - * "abc, def" and "abc,def" to mean the same thing. - * @param excludes - * Exclusion pattern. Follows the same format as the 'includes' parameter. - * Can be null. + * @param includes String like "foo/bar/*.xml" Multiple patterns can be + * separated by ',', and whitespace can surround ',' (so that you can write + * "abc, def" and "abc,def" to mean the same thing. + * @param excludes Exclusion pattern. Follows the same format as the + * 'includes' parameter. Can be null. * @since 1.172 */ public static FileSet createFileSet(File baseDir, String includes, String excludes) { @@ -1031,16 +1030,12 @@ public class Util { } /** - * Creates a symlink to baseDir+targetPath at baseDir+symlinkPath. - * <p> - * If there's a prior symlink at baseDir+symlinkPath, it will be overwritten. + * Creates a symlink to baseDir+targetPath at baseDir+symlinkPath. <p> If + * there's a prior symlink at baseDir+symlinkPath, it will be overwritten. * - * @param baseDir - * Base directory to resolve the 'symlinkPath' parameter. - * @param targetPath - * The file that the symlink should point to. - * @param symlinkPath - * Where to create a symlink in. + * @param baseDir Base directory to resolve the 'symlinkPath' parameter. + * @param targetPath The file that the symlink should point to. + * @param symlinkPath Where to create a symlink in. */ public static void createSymlink(File baseDir, String targetPath, String symlinkPath, TaskListener listener) throws InterruptedException { if (Functions.isWindows() || NO_SYMLINK) { @@ -1114,12 +1109,10 @@ public class Util { /** * Resolves symlink, if the given file is a symlink. Otherwise return null. - * <p> - * If the resolution fails, report an error. + * <p> If the resolution fails, report an error. * - * @param listener - * If we rely on an external command to resolve symlink, this is it. - * (TODO: try readlink(1) available on some platforms) + * @param listener If we rely on an external command to resolve symlink, + * this is it. (TODO: try readlink(1) available on some platforms) */ public static String resolveSymlink(File link, TaskListener listener) { if (Functions.isWindows()) { @@ -1140,14 +1133,14 @@ public class Util { /** * Encodes the URL by RFC 2396. * - * I thought there's another spec that refers to UTF-8 as the encoding, - * but don't remember it right now. + * I thought there's another spec that refers to UTF-8 as the encoding, but + * don't remember it right now. * * @since 1.204 - * @deprecated since 2008-05-13. This method is broken (see ISSUE#1666). It should probably - * be removed but I'm not sure if it is considered part of the public API - * that needs to be maintained for backwards compatibility. - * Use {@link #encode(String)} instead. + * @deprecated since 2008-05-13. This method is broken (see ISSUE#1666). It + * should probably be removed but I'm not sure if it is considered part of + * the public API that needs to be maintained for backwards compatibility. + * Use {@link #encode(String)} instead. */ @Deprecated public static String encodeRFC2396(String url) { @@ -1161,6 +1154,7 @@ public class Util { /** * Wraps with the error icon and the CSS class to render error message. + * * @since 1.173 */ public static String wrapToErrorSpan(String s) { @@ -1171,9 +1165,10 @@ public class Util { } /** - * Returns the parsed string if parsed successful; otherwise returns the default number. - * If the string is null, empty or a ParseException is thrown then the defaultNumber - * is returned. + * Returns the parsed string if parsed successful; otherwise returns the + * default number. If the string is null, empty or a ParseException is + * thrown then the defaultNumber is returned. + * * @param numberStr string to parse * @param defaultNumber number to return if the string can not be parsed * @return returns the parsed string; otherwise the default number @@ -1190,8 +1185,8 @@ public class Util { } /** - * Checks if the public method defined on the base type with the given arguments - * are overridden in the given derived type. + * Checks if the public method defined on the base type with the given + * arguments are overridden in the given derived type. */ public static boolean isOverridden(Class base, Class derived, String methodName, Class... types) { // the rewriteHudsonWar method isn't overridden. @@ -1206,8 +1201,7 @@ public class Util { /** * Returns a file name by changing its extension. * - * @param ext - * For example, ".zip" + * @param ext For example, ".zip" */ public static File changeExtension(File dst, String ext) { String p = dst.getPath(); @@ -1228,6 +1222,7 @@ public class Util { /** * Loads a key/value pair string as {@link Properties} + * * @since 1.392 */ public static Properties loadProperties(String properties) throws IOException { diff --git a/hudson-core/src/main/java/hudson/WorkspaceSnapshot.java b/hudson-core/src/main/java/hudson/WorkspaceSnapshot.java index 15c8413..2d3820f 100644 --- a/hudson-core/src/main/java/hudson/WorkspaceSnapshot.java +++ b/hudson-core/src/main/java/hudson/WorkspaceSnapshot.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -25,31 +25,29 @@ import java.io.IOException; /** * Represents a workspace snapshot created by {@link FileSystemProvisioner}. * - * <p> - * This class encapsulates a logic to use the snapshot elsewhere. - * The instance will be persisted with the {@link AbstractBuild} object - * as an {@link Action}. + * <p> This class encapsulates a logic to use the snapshot elsewhere. The + * instance will be persisted with the {@link AbstractBuild} object as an + * {@link Action}. * - * <p> - * TODO: how to garbage-collect this object, especially for zfs? - * perhaps when a new build is started? + * <p> TODO: how to garbage-collect this object, especially for zfs? perhaps + * when a new build is started? * * @see FileSystemProvisioner * @author Kohsuke Kawaguchi */ public abstract class WorkspaceSnapshot implements Action { + /** * Restores the snapshot to the given file system location. * - * @param owner - * The build that owns this action. It's always the same value for any given {@link WorkspaceSnapshot}, - * but passed in separately so that implementations don't need to keep them in fields. - * @param dst - * The file path to which the snapshot shall be restored to. - * @param listener - * Send the progress of the restoration to this listener. Never null. + * @param owner The build that owns this action. It's always the same value + * for any given {@link WorkspaceSnapshot}, but passed in separately so that + * implementations don't need to keep them in fields. + * @param dst The file path to which the snapshot shall be restored to. + * @param listener Send the progress of the restoration to this listener. + * Never null. */ - public abstract void restoreTo(AbstractBuild<?,?> owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException; + public abstract void restoreTo(AbstractBuild<?, ?> owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException; public String getIconFileName() { // by default, hide from the UI diff --git a/hudson-core/src/main/java/hudson/XmlFile.java b/hudson-core/src/main/java/hudson/XmlFile.java index 81af647..20cfc7c 100644 --- a/hudson-core/src/main/java/hudson/XmlFile.java +++ b/hudson-core/src/main/java/hudson/XmlFile.java @@ -7,10 +7,10 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: -* -* Kohsuke Kawaguchi - * + * Contributors: + * + * Kohsuke Kawaguchi + * * *******************************************************************************/ @@ -49,57 +49,51 @@ import java.util.logging.Logger; * Represents an XML data file that Hudson uses as a data file. * * - * <h2>Evolving data format</h2> - * <p> - * Changing data format requires a particular care so that users with - * the old data format can migrate to the newer data format smoothly. + * <h2>Evolving data format</h2> <p> Changing data format requires a particular + * care so that users with the old data format can migrate to the newer data + * format smoothly. * - * <p> - * Adding a field is the easiest. When you read an old XML that does - * not have any data, the newly added field is left to the VM-default - * value (if you let XStream create the object, such as - * {@link #read()} — which is the majority), or to the value initialized by the - * constructor (if the object is created via <tt>new</tt> and then its - * value filled by XStream, such as {@link #unmarshal(Object)}.) + * <p> Adding a field is the easiest. When you read an old XML that does not + * have any data, the newly added field is left to the VM-default value (if you + * let XStream create the object, such as {@link #read()} — which is the + * majority), or to the value initialized by the constructor (if the object is + * created via <tt>new</tt> and then its value filled by XStream, such as + * {@link #unmarshal(Object)}.) * - * <p> - * Removing a field requires that you actually leave the field with - * <tt>transient</tt> keyword. When you read the old XML, XStream - * will set the value to this field. But when the data is saved, - * the field will no longer will be written back to XML. - * (It might be possible to tweak XStream so that we can simply - * remove fields from the class. Any help appreciated.) + * <p> Removing a field requires that you actually leave the field with + * <tt>transient</tt> keyword. When you read the old XML, XStream will set the + * value to this field. But when the data is saved, the field will no longer + * will be written back to XML. (It might be possible to tweak XStream so that + * we can simply remove fields from the class. Any help appreciated.) * - * <p> - * Changing the data structure is usually a combination of the two - * above. You'd leave the old data store with <tt>transient</tt>, - * and then add the new data. When you are reading the old XML, - * only the old field will be set. When you are reading the new XML, - * only the new field will be set. You'll then need to alter the code - * so that it will be able to correctly handle both situations, - * and that as soon as you see data in the old field, you'll have to convert - * that into the new data structure, so that the next <tt>save</tt> operation - * will write the new data (otherwise you'll end up losing the data, because - * old fields will be never written back.) + * <p> Changing the data structure is usually a combination of the two above. + * You'd leave the old data store with <tt>transient</tt>, and then add the new + * data. When you are reading the old XML, only the old field will be set. When + * you are reading the new XML, only the new field will be set. You'll then need + * to alter the code so that it will be able to correctly handle both + * situations, and that as soon as you see data in the old field, you'll have to + * convert that into the new data structure, so that the next <tt>save</tt> + * operation will write the new data (otherwise you'll end up losing the data, + * because old fields will be never written back.) * - * <p> - * In some limited cases (specifically when the class is the root object - * to be read from XML, such as {@link Descriptor}), it is possible - * to completely and drastically change the data format. See - * {@link Descriptor#load()} for more about this technique. + * <p> In some limited cases (specifically when the class is the root object to + * be read from XML, such as {@link Descriptor}), it is possible to completely + * and drastically change the data format. See {@link Descriptor#load()} for + * more about this technique. * - * <p> - * There's a few other possibilities, such as implementing a custom - * {@link Converter} for XStream, or {@link XStream#alias(String, Class) registering an alias}. + * <p> There's a few other possibilities, such as implementing a custom + * {@link Converter} for XStream, or + * {@link XStream#alias(String, Class) registering an alias}. * * @author Kohsuke Kawaguchi */ public final class XmlFile { + private final XStream xs; private final File file; public XmlFile(File file) { - this(DEFAULT_XSTREAM,file); + this(DEFAULT_XSTREAM, file); } public XmlFile(XStream xs, File file) { @@ -115,16 +109,16 @@ public final class XmlFile { * Loads the contents of this file into a new object. */ public Object read() throws IOException { - LOGGER.fine("Reading "+file); + LOGGER.fine("Reading " + file); Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); try { return xs.fromXML(r); - } catch(StreamException e) { - throw new IOException2("Unable to read "+file,e); - } catch(ConversionException e) { - throw new IOException2("Unable to read "+file,e); - } catch(Error e) {// mostly reflection errors - throw new IOException2("Unable to read "+file,e); + } catch (StreamException e) { + throw new IOException2("Unable to read " + file, e); + } catch (ConversionException e) { + throw new IOException2("Unable to read " + file, e); + } catch (Error e) {// mostly reflection errors + throw new IOException2("Unable to read " + file, e); } finally { r.close(); } @@ -133,33 +127,32 @@ public final class XmlFile { /** * Loads the contents of this file into an existing object. * - * @return - * The unmarshalled object. Usually the same as <tt>o</tt>, but would be different - * if the XML representation is completely new. + * @return The unmarshalled object. Usually the same as <tt>o</tt>, but + * would be different if the XML representation is completely new. */ - public Object unmarshal( Object o ) throws IOException { - Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8")); + public Object unmarshal(Object o) throws IOException { + Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); try { - return xs.unmarshal(new XppReader(r),o); + return xs.unmarshal(new XppReader(r), o); } catch (StreamException e) { - throw new IOException2("Unable to read "+file,e); - } catch(ConversionException e) { - throw new IOException2("Unable to read "+file,e); - } catch(Error e) {// mostly reflection errors - throw new IOException2("Unable to read "+file,e); + throw new IOException2("Unable to read " + file, e); + } catch (ConversionException e) { + throw new IOException2("Unable to read " + file, e); + } catch (Error e) {// mostly reflection errors + throw new IOException2("Unable to read " + file, e); } finally { r.close(); } } - public void write( Object o ) throws IOException { + public void write(Object o) throws IOException { mkdirs(); AtomicFileWriter w = new AtomicFileWriter(file); try { w.write("<?xml version='1.0' encoding='UTF-8'?>\n"); - xs.toXML(o,w); + xs.toXML(o, w); w.commit(); - } catch(StreamException e) { + } catch (StreamException e) { throw new IOException2(e); } finally { w.abort(); @@ -173,7 +166,7 @@ public final class XmlFile { public void delete() { file.delete(); } - + public void mkdirs() { file.getParentFile().mkdirs(); } @@ -184,18 +177,20 @@ public final class XmlFile { } /** - * Opens a {@link Reader} that loads XML. - * This method uses {@link #sniffEncoding() the right encoding}, - * not just the system default encoding. + * Opens a {@link Reader} that loads XML. This method uses + * {@link #sniffEncoding() the right encoding}, not just the system default + * encoding. + * * @deprecated Should not be loading XML content using a character stream. */ @Deprecated public Reader readRaw() throws IOException { - return new InputStreamReader(new FileInputStream(file),sniffEncoding()); + return new InputStreamReader(new FileInputStream(file), sniffEncoding()); } /** * Returns the XML file read as a string. + * * @deprecated Should not be loading XML content using a character stream. */ @Deprecated @@ -206,23 +201,25 @@ public final class XmlFile { } /** - * Writes the raw XML to the given {@link Writer}. - * Writer will not be closed by the implementation. + * Writes the raw XML to the given {@link Writer}. Writer will not be closed + * by the implementation. + * * @deprecated Safer to use {@link #writeRawTo(OutputStream)}. */ @Deprecated public void writeRawTo(Writer w) throws IOException { Reader r = readRaw(); try { - Util.copyStream(r,w); + Util.copyStream(r, w); } finally { r.close(); } } /** - * Writes the raw XML to the given {@link OutputStream}. - * Stream will not be closed by the implementation. + * Writes the raw XML to the given {@link OutputStream}. Stream will not be + * closed by the implementation. + * * @since 2.1.1 */ public void writeRawTo(OutputStream os) throws IOException { @@ -237,23 +234,24 @@ public final class XmlFile { /** * Parses the beginning of the file and determines the encoding. * - * @throws IOException - * if failed to detect encoding. - * @return - * always non-null. + * @throws IOException if failed to detect encoding. + * @return always non-null. * @deprecated Should not be loading XML content using a character stream. */ @Deprecated public String sniffEncoding() throws IOException { class Eureka extends SAXException { + final String encoding; + public Eureka(String encoding) { this.encoding = encoding; } } try { - JAXP.newSAXParser().parse(file,new DefaultHandler() { + JAXP.newSAXParser().parse(file, new DefaultHandler() { private Locator loc; + @Override public void setDocumentLocator(Locator locator) { this.loc = locator; @@ -273,35 +271,36 @@ public final class XmlFile { } private void attempt() throws Eureka { - if(loc==null) return; + if (loc == null) { + return; + } if (loc instanceof Locator2) { Locator2 loc2 = (Locator2) loc; String e = loc2.getEncoding(); - if(e!=null) + if (e != null) { throw new Eureka(e); + } } } }); // can't reach here throw new AssertionError(); } catch (Eureka e) { - if(e.encoding==null) - throw new IOException("Failed to detect encoding of "+file); + if (e.encoding == null) { + throw new IOException("Failed to detect encoding of " + file); + } return e.encoding; } catch (SAXException e) { - throw new IOException2("Failed to detect encoding of "+file,e); + throw new IOException2("Failed to detect encoding of " + file, e); } catch (ParserConfigurationException e) { throw new AssertionError(e); // impossible } } - /** * {@link XStream} instance is supposed to be thread-safe. */ public static final XStream DEFAULT_XSTREAM = new XStream2(); - private static final Logger LOGGER = Logger.getLogger(XmlFile.class.getName()); - private static final SAXParserFactory JAXP = SAXParserFactory.newInstance(); static { |

