Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/src/main/java/hudson/lifecycle/WindowsInstallerLink.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@

import javax.servlet.ServletException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.net.URL;
Expand Down Expand Up @@ -141,7 +141,7 @@ public void doDoInstall(StaplerRequest req, StaplerResponse rsp, @QueryParameter

// install as a service
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamTaskListener task = new StreamTaskListener(baos);
StreamTaskListener task = new StreamTaskListener(baos, StandardCharsets.UTF_8);
task.getLogger().println("Installing a service");
int r = runElevated(new File(dir, "jenkins.exe"), "install", task, dir);
if(r!=0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.io.IOException;
import java.io.FileWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -130,7 +131,7 @@ public void restart() throws IOException, InterruptedException {
File home = me.getParentFile();

ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamTaskListener task = new StreamTaskListener(baos);
StreamTaskListener task = new StreamTaskListener(baos, StandardCharsets.UTF_8);
task.getLogger().println("Restarting a service");
String exe = System.getenv("WINSW_EXECUTABLE");
File executable;
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/model/AsyncAperiodicWork.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
Expand Down Expand Up @@ -190,7 +191,7 @@ protected StreamTaskListener createListener() {
}
}
try {
return new StreamTaskListener(f, true, null);
return new StreamTaskListener(f, true, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new Error(e);
}
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/model/AsyncPeriodicWork.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
Expand Down Expand Up @@ -173,7 +174,7 @@ protected StreamTaskListener createListener() {
}
}
try {
return new StreamTaskListener(f, true, null);
return new StreamTaskListener(f, true, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new Error(e);
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/hudson/model/Computer.java
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,14 @@ public WorkspaceList getWorkspaceList() {
* Gets the string representation of the agent log.
*/
public String getLog() throws IOException {
return Util.loadFile(getLogFile());
return Util.loadFile(getLogFile(), getDefaultCharset());
}

/**
* Used to URL-bind {@link AnnotatedLargeText}.
*/
public AnnotatedLargeText<Computer> getLogText() {
return new AnnotatedLargeText<Computer>(getLogFile(), Charset.defaultCharset(), false, this);
return new AnnotatedLargeText<Computer>(getLogFile(), getDefaultCharset(), false, this);
}

public ACL getACL() {
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/java/hudson/model/JDK.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
package hudson.model;

import hudson.util.StreamTaskListener;
import hudson.util.NullStream;
import hudson.util.FormValidation;
import hudson.Launcher;
import hudson.Extension;
Expand Down Expand Up @@ -157,7 +155,7 @@ public JDK forEnvironment(EnvVars environment) {
*/
public static boolean isDefaultJDKValid(Node n) {
try {
TaskListener listener = new StreamTaskListener(new NullStream());
TaskListener listener = TaskListener.NULL;
Launcher launcher = n.createLauncher(listener);
return launcher.launch().cmds("java","-fullversion").stdout(listener).join()==0;
} catch (IOException e) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/hudson/model/Queue.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
Expand Down Expand Up @@ -376,7 +376,7 @@ public void load() {
// first try the old format
File queueFile = getQueueFile();
if (queueFile.exists()) {
try (BufferedReader in = Files.newBufferedReader(Util.fileToPath(queueFile), Charset.defaultCharset())) {
try (BufferedReader in = Files.newBufferedReader(Util.fileToPath(queueFile), StandardCharsets.UTF_8)) {
String line;
while ((line = in.readLine()) != null) {
AbstractProject j = Jenkins.getInstance().getItemByFullName(line, AbstractProject.class);
Expand Down
52 changes: 31 additions & 21 deletions core/src/main/java/hudson/model/Run.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
import java.io.RandomAccessFile;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
Expand Down Expand Up @@ -267,6 +268,7 @@ private static enum State {
* @since 1.257
*/
protected String charset;
private transient Charset charsetInstance;

/**
* Keeps this log entries.
Expand Down Expand Up @@ -551,8 +553,18 @@ public boolean isLogUpdated() {
* @since 1.257
*/
public final @Nonnull Charset getCharset() {
if(charset==null) return Charset.defaultCharset();
return Charset.forName(charset);
if (charsetInstance==null)
return StandardCharsets.UTF_8;
return charsetInstance;
}

/**
* Sets the charset in which the log file is written.
* @since TODO
*/
public final void setCharset(Charset charset) {
this.charsetInstance = charset;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not enough. onLoad must also restore charsetInstance based on the persisted charset, or getCharset will wind up always returning UTF-8 after a restart.

this.charset = (charset==null ? null : charset.name());
}

/**
Expand Down Expand Up @@ -1111,7 +1123,7 @@ public boolean getHasArtifacts() {

private int addArtifacts(@Nonnull VirtualFile dir,
@Nonnull String path, @Nonnull String pathHref,
@Nonnull ArtifactList r, @Nonnull Artifact parent, int upTo) throws IOException {
@Nonnull ArtifactList r, Artifact parent, int upTo) throws IOException {
VirtualFile[] kids = dir.list();
Arrays.sort(kids);

Expand All @@ -1124,6 +1136,7 @@ private int addArtifacts(@Nonnull VirtualFile dir,
boolean collapsed = (kids.length==1 && parent!=null);
Artifact a;
if (collapsed) {
assert parent!=null;
// Collapse single items into parent node where possible:
a = new Artifact(parent.getFileName() + '/' + child, childPath,
sub.isDirectory() ? null : childHref, length,
Expand Down Expand Up @@ -1378,12 +1391,11 @@ public String toString() {
}

String message = "No such file: " + logFile;
return new ByteArrayInputStream(charset != null ? message.getBytes(charset) : message.getBytes());
return new ByteArrayInputStream(message.getBytes(getCharset()));
}

public @Nonnull Reader getLogReader() throws IOException {
if (charset==null) return new InputStreamReader(getLogInputStream());
else return new InputStreamReader(getLogInputStream(),charset);
return new InputStreamReader(getLogInputStream(), getCharset());
}

/**
Expand Down Expand Up @@ -1414,7 +1426,7 @@ public void writeLogTo(long offset, @Nonnull XMLOutput out) throws IOException {
*/
public void writeWholeLogTo(@Nonnull OutputStream out) throws IOException, InterruptedException {
long pos = 0;
AnnotatedLargeText logText;
AnnotatedLargeText<Run<JobT, RunT>> logText;
logText = getLogText();
pos = logText.writeLogTo(pos, out);

Expand All @@ -1431,8 +1443,8 @@ public void writeWholeLogTo(@Nonnull OutputStream out) throws IOException, Inter
* Used to URL-bind {@link AnnotatedLargeText}.
* @return A {@link Run} log with annotations
*/
public @Nonnull AnnotatedLargeText getLogText() {
return new AnnotatedLargeText(getLogFile(),getCharset(),!isLogUpdated(),this);
public @Nonnull AnnotatedLargeText<Run<JobT, RunT>> getLogText() {
return new AnnotatedLargeText<>(getLogFile(), getCharset(), !isLogUpdated(), this);
}

@Override
Expand Down Expand Up @@ -1697,15 +1709,14 @@ protected final void execute(@Nonnull RunExecution job) {
long start = System.currentTimeMillis();

try {
Computer computer = Computer.currentComputer();
if (computer != null) {
setCharset(computer.getDefaultCharset());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is what I think is really wrong. We should change the charset of all builds to be UTF-8, unconditionally, so that miscellaneous messages can always be safely written to the log file; but make sure that anything which copies external process output (namely, Launcher) transcodes that output on either the master or remote side.

Cf. my corresponding changes for Pipeline in jenkinsci/workflow-job-plugin#27 and jenkinsci/durable-task-plugin#29, with integration test (ShellStepTest.encoding) in jenkinsci/workflow-durable-task-step-plugin#21.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sure you are right. Ideally only UTF-8 would be used, though I was hesitant to go through and rip out anything relating to charsets. Right now I have changed the implementations of Computer.getDefaultCharset() to return StandardCharsets.UTF_8, so effectively this is what is being done, but without removing the scaffolding just yet.

}
logger = createLogger();
listener = createBuildListener(job, logger, getCharset());

try {
Computer computer = Computer.currentComputer();
Charset charset = null;
if (computer != null) {
charset = computer.getDefaultCharset();
this.charset = charset.name();
}
logger = createLogger();
listener = createBuildListener(job, logger, charset);
listener.started(getCauses());

Authentication auth = Jenkins.getAuthentication();
Expand Down Expand Up @@ -1869,7 +1880,7 @@ private void createSymlink(@Nonnull TaskListener listener, @Nonnull String name,
/**
* Handles a fatal build problem (exception) that occurred during the build.
*/
private void handleFatalBuildProblem(@Nonnull BuildListener listener, @Nonnull Throwable e) {
private void handleFatalBuildProblem(BuildListener listener, @Nonnull Throwable e) {
if(listener!=null) {
LOGGER.log(FINE, getDisplayName()+" failed to build",e);

Expand Down Expand Up @@ -2127,8 +2138,7 @@ public void doBuildNumber(StaplerResponse rsp) throws IOException {
* Returns the build time stamp in the body.
*/
public void doBuildTimestamp( StaplerRequest req, StaplerResponse rsp, @QueryParameter String format) throws IOException {
rsp.setContentType("text/plain");
rsp.setCharacterEncoding("US-ASCII");
rsp.setContentType("text/plain;charset=UTF-8");
rsp.setStatus(HttpServletResponse.SC_OK);
DateFormat df = format==null ?
DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT, Locale.ENGLISH) :
Expand All @@ -2140,7 +2150,7 @@ public void doBuildTimestamp( StaplerRequest req, StaplerResponse rsp, @QueryPar
* Sends out the raw console output.
*/
public void doConsoleText(StaplerRequest req, StaplerResponse rsp) throws IOException {
rsp.setContentType("text/plain;charset=UTF-8");
rsp.setContentType("text/plain;charset=" + getCharset().name());
try (InputStream input = getLogInputStream();
OutputStream os = rsp.getCompressedOutputStream(req);
PlainTextConsoleOutputStream out = new PlainTextConsoleOutputStream(os)) {
Expand Down
13 changes: 9 additions & 4 deletions core/src/main/java/hudson/model/StreamBuildListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
* @author Kohsuke Kawaguchi
*/
public class StreamBuildListener extends StreamTaskListener implements BuildListener {

/**
* @deprecated use {@link #StreamBuildListener(java.io.OutputStream, java.nio.charset.Charset)} instead.
*/
@Deprecated
public StreamBuildListener(OutputStream out) {
super(out);
}

public StreamBuildListener(OutputStream out, Charset charset) {
super(out, charset);
}
Expand All @@ -47,10 +56,6 @@ public StreamBuildListener(File out, Charset charset) throws IOException {
super(out, charset);
}

public StreamBuildListener(OutputStream w) {
super(w);
}

/**
* @deprecated as of 1.349
* The caller should use {@link #StreamBuildListener(OutputStream, Charset)} to pass in
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/hudson/model/TaskListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ default PrintWriter _error(String prefix, String msg) {

// annotate(new HudsonExceptionNote()) if and when this is made to do something
Charset charset = getCharset();
return new PrintWriter(charset != null ? new OutputStreamWriter(out, charset) : new OutputStreamWriter(out), true);
return new PrintWriter(new OutputStreamWriter(out, charset), true);
}

/**
Expand Down Expand Up @@ -154,5 +154,5 @@ default PrintWriter fatalError(String format, Object... args) {
/**
* {@link TaskListener} that discards the output.
*/
TaskListener NULL = new StreamTaskListener(new NullStream());
TaskListener NULL = new StreamTaskListener(new NullStream(), StandardCharsets.UTF_8);
}
10 changes: 5 additions & 5 deletions core/src/main/java/hudson/model/TaskThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import java.io.IOException;
import java.io.Reader;
import java.lang.ref.WeakReference;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.kohsuke.stapler.framework.io.LargeText;
import org.kohsuke.stapler.framework.io.ByteBuffer;

Expand Down Expand Up @@ -187,8 +187,8 @@ public static ListenerAndText forMemory(TaskAction context) {
ByteBuffer log = new ByteBuffer();

return new ListenerAndText(
new StreamTaskListener(log),
new AnnotatedLargeText<TaskAction>(log,Charset.defaultCharset(),false,context)
new StreamTaskListener(log, StandardCharsets.UTF_8),
new AnnotatedLargeText<TaskAction>(log, StandardCharsets.UTF_8, false, context)
);
}

Expand All @@ -197,8 +197,8 @@ public static ListenerAndText forMemory(TaskAction context) {
*/
public static ListenerAndText forFile(File f, TaskAction context) throws IOException {
return new ListenerAndText(
new StreamTaskListener(f),
new AnnotatedLargeText<TaskAction>(f,Charset.defaultCharset(),false,context)
new StreamTaskListener(f, StandardCharsets.UTF_8),
new AnnotatedLargeText<TaskAction>(f, StandardCharsets.UTF_8, false, context)
);
}
}
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/java/hudson/os/solaris/ZFSInstaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -225,7 +227,7 @@ public void doStart(StaplerRequest req, StaplerResponse rsp, @QueryParameter Str

final String datasetName;
ByteArrayOutputStream log = new ByteArrayOutputStream();
StreamTaskListener listener = new StreamTaskListener(log);
StreamTaskListener listener = new StreamTaskListener(log, StandardCharsets.UTF_8);
try {
datasetName = createZfsFileSystem(listener,username,password);
} catch (Exception e) {
Expand Down Expand Up @@ -285,7 +287,7 @@ public static AdministrativeMonitor init() {
String migrationTarget = SystemProperties.getString(ZFSInstaller.class.getName() + ".migrate");
if(migrationTarget!=null) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamTaskListener listener = new StreamTaskListener(new ForkOutputStream(System.out, out));
StreamTaskListener listener = new StreamTaskListener(new ForkOutputStream(System.out, out), Charset.defaultCharset());
try {
if(migrate(listener,migrationTarget)) {
// completed successfully
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/slaves/AbstractCloudSlave.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void terminate() throws InterruptedException, IOException {
}
try {
// TODO: send the output to somewhere real
_terminate(new StreamTaskListener(System.out, Charset.defaultCharset()));
_terminate(StreamTaskListener.fromStdout());
} finally {
try {
Jenkins.getInstance().removeNode(this);
Expand Down
Loading