提交 db93c57e 编写于 作者: M mindless

Add @Override annotations, one copyright header and some tab->ws


git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@21655 71c3de6d-444a-0410-be80-ed276b4c234a
上级 9fed9823
......@@ -1340,6 +1340,7 @@ public final class FilePath implements Serializable {
setProject(new org.apache.tools.ant.Project());
}
@Override
protected void doFileOperations() {
copySize = super.fileCopyMap.size();
super.doFileOperations();
......@@ -1451,6 +1452,7 @@ public final class FilePath implements Serializable {
this.filter = filter;
}
@Override
void scan(File dir, FileVisitor visitor) throws IOException {
super.scan(dir,visitor.with(filter));
}
......@@ -1575,6 +1577,7 @@ public final class FilePath implements Serializable {
// TarOutputStream uses TarBuffer internally,
// which flushes the stream for each block. this creates unnecessary
// data stream fragmentation, and flush request to a remote, which slows things down.
@Override
public void flush() throws IOException {
// so don't do anything in flush
}
......@@ -1967,7 +1970,7 @@ public final class FilePath implements Serializable {
return validateRelativeDirectory(value,true);
}
@Deprecated
@Deprecated @Override
public String toString() {
// to make writing JSPs easily, return local
return remote;
......
......@@ -670,12 +670,14 @@ public abstract class Launcher {
/**
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
super.terminate(e);
ProcessTree pt = ProcessTree.get();
pt.killAll(proc,cookie);
}
@Override
public synchronized void close() throws IOException {
super.close();
// wait for all the output from the process to be picked up
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson;
import hudson.model.TaskListener;
......
......@@ -69,6 +69,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
setCombination(c);
}
@Override
public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
// directory name is not a name for us --- it's taken from the combination name
super.onLoad(parent, combination.toString());
......@@ -115,6 +116,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
return n;
}
@Override
public int assignBuildNumber() throws IOException {
int nb = getNextBuildNumber();
MatrixRun r = getLastBuild();
......@@ -128,6 +130,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
return combination.toCompactString(getParent().getAxes());
}
@Override
public MatrixProject getParent() {
return (MatrixProject)super.getParent();
}
......@@ -187,6 +190,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
protected void buildDependencyGraph(DependencyGraph graph) {
}
@Override
public MatrixConfiguration asProject() {
return this;
}
......@@ -259,6 +263,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
* @deprecated
* Not supported.
*/
@Override
public void setJDK(JDK jdk) throws IOException {
throw new UnsupportedOperationException();
}
......@@ -267,6 +272,7 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
* @deprecated
* Value is controlled by {@link MatrixProject}.
*/
@Override
public void setLogRotator(LogRotator logRotator) {
throw new UnsupportedOperationException();
}
......@@ -308,5 +314,4 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
public boolean scheduleBuild(ParametersAction parameters, Cause c) {
return Hudson.getInstance().getQueue().schedule(this, getQuietPeriod(), parameters, new CauseAction(c))!=null;
}
}
......@@ -228,6 +228,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
this.touchStoneResultCondition = touchStoneResultCondition;
}
@Override
protected void updateTransientActions() {
synchronized(transientActions) {
super.updateTransientActions();
......@@ -274,6 +275,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
};
}
@Override
public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
super.onLoad(parent,name);
Collections.sort(axes); // perhaps the file was edited on disk and the sort order might have been broken
......@@ -283,6 +285,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
rebuildConfigurations();
}
@Override
public void logRotate() throws IOException, InterruptedException {
super.logRotate();
// perform the log rotation of inactive configurations to make sure
......@@ -452,6 +455,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
return f;
}
@Override
public Hudson getParent() {
return Hudson.getInstance();
}
......@@ -540,6 +544,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
return this;
}
@Override
public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) {
try {
MatrixConfiguration item = getItem(token);
......@@ -551,6 +556,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
return super.getDynamic(token,req,rsp);
}
@Override
protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException {
super.submit(req, rsp);
......
......@@ -72,6 +72,7 @@ public final class FingerprintMap extends KeyedDataStorage<Fingerprint,Fingerpri
return super.getOrCreate(md5sum, new FingerprintParams(build,fileName));
}
@Override
protected Fingerprint get(String md5sum, boolean createIfNotExist, FingerprintParams createParams) throws IOException {
// sanity check
if(md5sum.length()!=32)
......
......@@ -332,6 +332,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
public CloudList() {// needed for XStream deserialization
}
@Override
protected void onModified() throws IOException {
super.onModified();
Hudson.getInstance().trimLabels();
......@@ -662,7 +663,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*
* @deprecated
*/
@Deprecated
@Deprecated @Override
public String getNodeName() {
return "";
}
......@@ -1288,6 +1289,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
return queue;
}
@Override
public String getDisplayName() {
return Messages.Hudson_DisplayName();
}
......@@ -1601,6 +1603,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
return new FilePath(getRootDir());
}
@Override
public FilePath createPath(String absolutePath) {
return new FilePath((VirtualChannel)null,absolutePath);
}
......@@ -1722,6 +1725,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*
* @see AuthorizationStrategy#getRootACL()
*/
@Override
public ACL getACL() {
return authorizationStrategy.getRootACL();
}
......@@ -1940,6 +1944,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
return fixNull(label).trim();
}
@Override
public Label getSelfLabel() {
return getLabel("master");
}
......@@ -2636,6 +2641,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
rsp.sendRedirect2(req.getContextPath()+"/");
new Thread("Hudson config reload thread") {
@Override
public void run() {
try {
load();
......@@ -3160,6 +3166,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
/**
* Returns "" to match with {@link Hudson#getNodeName()}.
*/
@Override
public String getName() {
return "";
}
......@@ -3179,6 +3186,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
return Messages.Hudson_Computer_Caption();
}
@Override
public String getUrl() {
return "computer/(master)/";
}
......@@ -3195,6 +3203,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
rsp.sendError(SC_BAD_REQUEST);
}
@Override
public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
// the master node isn't in the Hudson.getNodes(), so this method makes no sense.
throw new UnsupportedOperationException();
......
......@@ -38,7 +38,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
......@@ -140,5 +139,4 @@ public class ParametersAction implements Action, Iterable<ParameterValue>, Queue
return !parameters.equals(new HashSet<ParameterValue>(this.parameters));
}
}
}
......@@ -81,6 +81,7 @@ public abstract class Project<P extends Project<P,B>,B extends Build<P,B>>
super(parent,name);
}
@Override
public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
super.onLoad(parent, name);
......@@ -197,6 +198,7 @@ public abstract class Project<P extends Project<P,B>,B extends Build<P,B>>
updateTransientActions(); // to pick up transient actions from builder, publisher, etc.
}
@Override
protected void updateTransientActions() {
synchronized(transientActions) {
super.updateTransientActions();
......
......@@ -273,7 +273,7 @@ public class Queue extends ResourceController implements Saveable {
}
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to load the queue file " + getQueueFile(), e);
LOGGER.log(Level.WARNING, "Failed to load the queue file " + getXMLQueueFile(), e);
}
}
......@@ -293,7 +293,7 @@ public class Queue extends ResourceController implements Saveable {
try {
new XmlFile(XSTREAM, getXMLQueueFile()).write(items);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to write out the queue file " + getQueueFile(), e);
LOGGER.log(Level.WARNING, "Failed to write out the queue file " + getXMLQueueFile(), e);
}
}
......@@ -1062,7 +1062,7 @@ public class Queue extends ResourceController implements Saveable {
/**
* Used to render the HTML. Should be a human readable text of what this executable is.
*/
String toString();
@Override String toString();
}
/*package*/ static final class FutureImpl extends AsyncFutureImpl<Executable> {
......
......@@ -105,6 +105,7 @@ public final class Result implements Serializable, CustomExportedBean {
}
@Override
public String toString() {
return name;
}
......
......@@ -543,6 +543,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return state ==State.NOT_STARTED;
}
@Override
public String toString() {
return getFullDisplayName();
}
......@@ -876,6 +877,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return href;
}
@Override
public String toString() {
return relativePath;
}
......@@ -910,6 +912,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return null;
}
@Override
protected SearchIndexBuilder makeSearchIndex() {
SearchIndexBuilder builder = super.makeSearchIndex()
.add("console")
......@@ -1592,6 +1595,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
* The entry unique ID needs to be tied to a project, so that
* new builds will replace the old result.
*/
@Override
public String getEntryID(Run e) {
// can't use a meaningful year field unless we remember when the job was created.
return "tag:hudson.dev.java.net,2008:"+e.getParent().getAbsoluteUrl();
......
......@@ -312,6 +312,7 @@ public abstract class Slave extends Node implements Serializable {
return (SlaveComputer)toComputer();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
......@@ -321,6 +322,7 @@ public abstract class Slave extends Node implements Serializable {
return name.equals(that.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
......
......@@ -187,6 +187,7 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
}
}
@Override
public void run() {
try {
long startTime = System.currentTimeMillis();
......
......@@ -400,6 +400,7 @@ public final class CVSChangeLogSet extends ChangeLogSet<CVSChangeLog> {
return new Revision(p);
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
for (int n : numbers) {
......
......@@ -208,6 +208,7 @@ public class CVSSCM extends SCM implements Serializable {
return workspace.child(getAllModulesNormalized()[0]);
}
@Override
public FilePath[] getModuleRoots(FilePath workspace) {
if (!flatten) {
final String[] moduleLocations = getAllModulesNormalized();
......@@ -238,8 +239,7 @@ public class CVSSCM extends SCM implements Serializable {
private Pattern[] getExcludedRegionsPatterns() {
String[] excludedRegions = getExcludedRegionsNormalized();
if (excludedRegions != null)
{
if (excludedRegions != null) {
Pattern[] patterns = new Pattern[excludedRegions.length];
int i = 0;
......@@ -832,6 +832,7 @@ public class CVSSCM extends SCM implements Serializable {
final boolean[] hadError = new boolean[1];
ChangeLogTask task = new ChangeLogTask() {
@Override
public void log(String msg, int msgLevel) {
if(msgLevel==org.apache.tools.ant.Project.MSG_ERR)
hadError[0] = true;
......@@ -929,10 +930,12 @@ public class CVSSCM extends SCM implements Serializable {
}
}
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
@Override
public void buildEnvVars(AbstractBuild build, Map<String, String> env) {
if(cvsRsh!=null)
env.put("CVS_RSH",cvsRsh);
......@@ -1075,6 +1078,7 @@ public class CVSSCM extends SCM implements Serializable {
load();
}
@Override
protected void convert(Map<String, Object> oldPropertyBag) {
cvsPassFile = (String)oldPropertyBag.get("cvspass");
}
......@@ -1115,6 +1119,7 @@ public class CVSSCM extends SCM implements Serializable {
return noCompression;
}
@Override
public boolean configure( StaplerRequest req, JSONObject o ) {
cvsPassFile = fixEmptyAndTrim(req.getParameter("cvspassFile"));
cvsExe = fixEmptyAndTrim(o.getString("cvsExe"));
......@@ -1576,6 +1581,7 @@ public class CVSSCM extends SCM implements Serializable {
this.tagSet = tagSet;
}
@Override
public synchronized void start() {
for (Entry<AbstractBuild, String> e : tagSet.entrySet()) {
TagAction ta = e.getKey().getAction(TagAction.class);
......
......@@ -231,10 +231,12 @@ public abstract class AuthorizationStrategy implements Describable<Authorization
return Messages.AuthorizationStrategy_DisplayName();
}
@Override
public AuthorizationStrategy newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return UNSECURED;
}
@Override
public String getHelpFile() {
return "/help/security/no-authorization.html";
}
......
......@@ -241,6 +241,7 @@ public class GlobalMatrixAuthorizationStrategy extends AuthorizationStrategy {
return Messages.GlobalMatrixAuthorizationStrategy_DisplayName();
}
@Override
public AuthorizationStrategy newInstance(StaplerRequest req, JSONObject formData) throws FormException {
GlobalMatrixAuthorizationStrategy gmas = create();
for(Map.Entry<String,JSONObject> r : (Set<Map.Entry<String,JSONObject>>)formData.getJSONObject("data").entrySet()) {
......
......@@ -436,6 +436,7 @@ public class HudsonPrivateSecurityRealm extends SecurityRealm implements ModelOb
return Details.fromPlainPassword(Util.fixNull(pwd));
}
@Override
public boolean isEnabled() {
return Hudson.getInstance().getSecurityRealm() instanceof HudsonPrivateSecurityRealm;
}
......@@ -544,6 +545,7 @@ public class HudsonPrivateSecurityRealm extends SecurityRealm implements ModelOb
return Messages.HudsonPrivateSecurityRealm_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/security/private-realm.html";
}
......
......@@ -391,6 +391,7 @@ public abstract class SecurityRealm implements Describable<SecurityRealm>, Exten
* This special instance is not configurable explicitly,
* so it doesn't have a descriptor.
*/
@Override
public Descriptor<SecurityRealm> getDescriptor() {
return null;
}
......
......@@ -72,6 +72,7 @@ public class Channels {
/**
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
super.terminate(e);
try {
......@@ -85,6 +86,7 @@ public class Channels {
}
}
@Override
public synchronized void close() throws IOException {
super.close();
// wait for Maven to complete
......@@ -106,12 +108,14 @@ public class Channels {
/**
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
super.terminate(e);
proc.destroy();
// the stderr copier should exit by itself
}
@Override
public synchronized void close() throws IOException {
super.close();
// wait for Maven to complete
......
......@@ -131,6 +131,7 @@ public class SlaveComputer extends Computer {
return isUnix;
}
@Override
public Slave getNode() {
return (Slave)super.getNode();
}
......@@ -283,6 +284,7 @@ public class SlaveComputer extends Computer {
Channel channel = new Channel(nodeName,threadPoolForRemoting, Channel.Mode.NEGOTIATE,
in,out, launchLog);
channel.addListener(new Channel.Listener() {
@Override
public void onClosed(Channel c,IOException cause) {
SlaveComputer.this.channel = null;
offlineCause = new ChannelTermination(cause);
......
......@@ -235,6 +235,7 @@ public class Ant extends Builder {
return base.child("build.xml");
}
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
......@@ -268,6 +269,7 @@ public class Ant extends Builder {
installations = (AntInstallation[]) oldPropertyBag.get("installations");
}
@Override
public String getHelpFile() {
return "/help/project-config/ant.html";
}
......@@ -280,6 +282,7 @@ public class Ant extends Builder {
return installations;
}
@Override
public Ant newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return (Ant)req.bindJSON(clazz,formData);
}
......
......@@ -95,6 +95,7 @@ public class ArtifactArchiver extends Recorder {
}
}
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException {
if(artifacts.length()==0) {
listener.error(Messages.ArtifactArchiver_NoIncludes());
......@@ -137,7 +138,8 @@ public class ArtifactArchiver extends Recorder {
return true;
}
public @Override boolean prebuild(AbstractBuild<?, ?> build, BuildListener listener) {
@Override
public boolean prebuild(AbstractBuild<?, ?> build, BuildListener listener) {
if(latestOnly) {
AbstractBuild<?,?> b = build.getProject().getLastCompletedBuild();
Result bestResultSoFar = Result.NOT_BUILT;
......@@ -190,6 +192,7 @@ public class ArtifactArchiver extends Recorder {
return FilePath.validateFileMask(project.getSomeWorkspace(),value);
}
@Override
public ArtifactArchiver newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindJSON(ArtifactArchiver.class,formData);
}
......
......@@ -203,6 +203,7 @@ public class Fingerprinter extends Recorder implements Serializable {
return Messages.Fingerprinter_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/project-config/fingerprint.html";
}
......@@ -214,6 +215,7 @@ public class Fingerprinter extends Recorder implements Serializable {
return FilePath.validateFileMask(project.getSomeWorkspace(),value);
}
@Override
public Publisher newInstance(StaplerRequest req) {
return new Fingerprinter(
req.getParameter("fingerprint_targets").trim(),
......
......@@ -190,6 +190,7 @@ public class Mailer extends Notifier {
/**
* For backward compatibility.
*/
@Override
protected void convert(Map<String, Object> oldPropertyBag) {
defaultSuffix = (String)oldPropertyBag.get("mail.default.suffix");
hudsonUrl = (String)oldPropertyBag.get("mail.hudson.url");
......@@ -203,6 +204,7 @@ public class Mailer extends Notifier {
return Messages.Mailer_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/project-config/mailer.html";
}
......@@ -250,6 +252,7 @@ public class Mailer extends Notifier {
final String un = getSmtpAuthUserName();
if(un==null) return null;
return new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(getSmtpAuthUserName(),getSmtpAuthPassword());
}
......@@ -344,6 +347,7 @@ public class Mailer extends Notifier {
this.smtpPort = smtpPort;
}
@Override
public Publisher newInstance(StaplerRequest req) {
Mailer m = new Mailer();
req.bindParameters(m,"mailer_");
......@@ -448,10 +452,10 @@ public class Mailer extends Notifier {
}
public UserProperty newInstance(User user) {
return new UserProperty(null);
}
@Override
public UserProperty newInstance(StaplerRequest req) throws FormException {
return new UserProperty(req.getParameter("email.address"));
}
......
......@@ -311,11 +311,13 @@ public class Maven extends Builder {
return true;
}
@Override
protected void convert(Map<String, Object> oldPropertyBag) {
if(oldPropertyBag.containsKey("installations"))
installations = (MavenInstallation[]) oldPropertyBag.get("installations");
}
@Override
public String getHelpFile() {
return "/help/project-config/maven.html";
}
......
......@@ -67,6 +67,7 @@ public abstract class Publisher extends BuildStepCompatibilityLayer implements B
* Don't extend from {@link Publisher} directly. Instead, choose {@link Recorder} or {@link Notifier}
* as your base class.
*/
@Deprecated
protected Publisher() {
}
......@@ -92,7 +93,7 @@ public abstract class Publisher extends BuildStepCompatibilityLayer implements B
}
/**
* Returne true if this {@link Publisher} needs to run after the build result is
* Return true if this {@link Publisher} needs to run after the build result is
* fully finalized.
*
* <p>
......
......@@ -236,6 +236,7 @@ public class JUnitResultArchiver extends Recorder implements Serializable,
return Messages.JUnitResultArchiver_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/tasks/junit/report.html";
}
......
......@@ -57,16 +57,19 @@ public class ChartUtil {
return this.build.number-that.build.number;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof NumberOnlyBuildLabel)) return false;
NumberOnlyBuildLabel that = (NumberOnlyBuildLabel) o;
return build==that.build;
}
@Override
public int hashCode() {
return build.hashCode();
}
@Override
public String toString() {
return build.getDisplayName();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册