11/*
2+ * Copyright (c) 2025 Contributors to the Eclipse Foundation
23 * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved.
34 *
45 * This program and the accompanying materials are made available under the
2223
2324import jakarta .inject .Inject ;
2425
26+ import java .lang .System .Logger ;
27+
2528import org .glassfish .api .ActionReport ;
2629import org .glassfish .api .I18n ;
2730import org .glassfish .api .Param ;
3942import org .glassfish .security .services .common .SubjectUtil ;
4043import org .jvnet .hk2 .annotations .Service ;
4144
45+ import static java .lang .System .Logger .Level .DEBUG ;
46+ import static java .lang .System .Logger .Level .ERROR ;
47+ import static java .lang .System .Logger .Level .WARNING ;
4248import static org .glassfish .api .admin .AdminCommandState .State .COMPLETED ;
4349import static org .glassfish .api .admin .AdminCommandState .State .PREPARED ;
4450import static org .glassfish .api .admin .AdminCommandState .State .REVERTED ;
6066@ AccessRequired (resource ="jobs/job/$jobID" , action ="attach" )
6167public class AttachCommand implements AdminCommand , AdminCommandListener {
6268
63-
6469 public static final String COMMAND_NAME = "attach" ;
65- protected final static LocalStringManagerImpl strings = new LocalStringManagerImpl (AttachCommand .class );
66-
67- protected AdminCommandEventBroker eventBroker ;
68- protected Job attached ;
70+ private static final LocalStringManagerImpl strings = new LocalStringManagerImpl (AttachCommand .class );
71+ private static final Logger LOG = System .getLogger (AttachCommand .class .getName ());
6972
7073 @ Inject
71- JobManagerService registry ;
74+ private JobManagerService registry ;
7275
73- @ Param (primary =true , optional =false , multiple =false )
74- protected String jobID ;
76+ @ Param (primary = true , optional = false , multiple = false )
77+ private String jobID ;
78+
79+ private AdminCommandEventBroker <?> eventBroker ;
80+ private Job attached ;
7581
7682 @ Override
7783 public void execute (AdminCommandContext context ) {
7884 eventBroker = context .getEventBroker ();
79-
8085 attached = registry .get (jobID );
81- JobInfo jobInfo = null ;
82- String jobName = null ;
83-
86+ final JobInfo jobInfo ;
8487 if (attached == null ) {
85- //try for completed jobs
86- if (registry .getCompletedJobs (registry .getJobsFile ()) != null ) {
87- jobInfo = (JobInfo ) registry .getCompletedJobForId (jobID );
88- }
89- if (jobInfo != null ) {
90- jobName = jobInfo .jobName ;
91- }
92-
88+ LOG .log (DEBUG , "Trying to find completed job id: {0}" , jobID );
89+ jobInfo = registry .getCompletedJobForId (jobID );
90+ } else {
91+ jobInfo = null ;
9392 }
94-
95- attach (attached ,jobInfo ,context ,jobName );
96-
93+ final String jobName = jobInfo == null ? null : jobInfo .jobName ;
94+ attach (jobInfo , context , jobName );
9795 }
9896
9997 @ Override
@@ -114,13 +112,16 @@ public void onAdminCommandEvent(String name, Object event) {
114112
115113 protected void purgeJob (String jobid ) {
116114 try {
115+ Thread .sleep (1000L );
117116 registry .purgeJob (jobid );
118117 registry .purgeCompletedJobForId (jobid );
119118 } catch (Exception ex ) {
119+ LOG .log (ERROR , "Failed to purge job with id: {1}" , jobid );
120120 }
121121 }
122122
123- public void attach (Job attached , JobInfo jobInfo , AdminCommandContext context ,String jobName ) {
123+
124+ private void attach (JobInfo jobInfo , AdminCommandContext context , String jobName ) {
124125 ActionReport ar = context .getActionReport ();
125126 String attachedUser = SubjectUtil .getUsernamesFromSubject (context .getSubject ()).get (0 );
126127 if ((attached == null && jobInfo == null ) || (attached != null && attached .getName ().startsWith ("_" ))
@@ -129,65 +130,62 @@ public void attach(Job attached, JobInfo jobInfo, AdminCommandContext context,St
129130 ar .setMessage (strings .getLocalString ("attach.wrong.commandinstance.id" , "Job with id {0} does not exist." , jobID ));
130131 return ;
131132 }
132-
133- if (attached != null ) {
134- String jobInitiator = attached .getSubjectUsernames ().get (0 );
135- if (!attachedUser .equals ( jobInitiator )) {
136- ar .setActionExitCode (ActionReport .ExitCode .FAILURE );
137- ar .setMessage (strings .getLocalString ("user.not.authorized" ,
138- "User {0} not authorized to attach to job {1}" , attachedUser , jobID ));
139- return ;
140- }
141- }
142- if (attached != null ) {
143- //Very sensitive locking part
144- AdminCommandEventBroker attachedBroker = attached .getEventBroker ();
145- CommandProgress commandProgress = attached .getCommandProgress ();
146- if (commandProgress == null ) {
147- synchronized (attachedBroker ) {
148- onAdminCommandEvent (AdminCommandStateImpl .EVENT_STATE_CHANGED , attached );
149- attachedBroker .registerListener (".*" , this );
150- }
151- } else {
152- synchronized (commandProgress ) {
153- onAdminCommandEvent (AdminCommandStateImpl .EVENT_STATE_CHANGED , attached );
154- onAdminCommandEvent (CommandProgress .EVENT_PROGRESSSTATUS_STATE , attached .getCommandProgress ());
155- attachedBroker .registerListener (".*" , this );
156- }
157- }
158- synchronized (attached ) {
159- while (attached .getState ().equals (PREPARED ) ||
160- attached .getState ().equals (RUNNING ) ||
161- attached .getState ().equals (RUNNING_RETRYABLE )) {
162- try {
163- attached .wait (1000 *60 *5 ); //5000L just to be sure
164- } catch (InterruptedException ex ) {}
165- }
166- if (attached .getState ().equals (COMPLETED ) || attached .getState ().equals (REVERTED )) {
167- String commandUser = attached .getSubjectUsernames ().get (0 );
168- //In most cases if the user who attaches to the command is the same
169- //as one who started it then purge the job once it is completed
170- if ((commandUser != null && commandUser .equals (attachedUser )) && attached .isOutboundPayloadEmpty ()) {
171- purgeJob (attached .getId ());
172-
173- }
174- ar .setActionExitCode (attached .getActionReport ().getActionExitCode ());
175- ar .appendMessage (strings .getLocalString ("attach.finished" , "Command {0} executed with status {1}" ,attached .getName (),attached .getActionReport ().getActionExitCode ()));
176- }
177- }
178- } else {
179-
133+ if (attached == null ) {
180134 if (jobInfo != null && (jobInfo .state .equals (COMPLETED .toString ()) || jobInfo .state .equals (REVERTED .toString ()))) {
181-
182135 //In most cases if the user who attaches to the command is the same
183136 //as one who started it then purge the job once it is completed
184137 if (attachedUser != null && attachedUser .equals ( jobInfo .user )) {
138+ LOG .log (WARNING , "" );
185139 purgeJob (jobInfo .jobId );
186-
187140 }
188141 ar .setActionExitCode (ActionReport .ExitCode .SUCCESS );
189142 ar .appendMessage (strings .getLocalString ("attach.finished" , "Command {0} executed{1}" ,jobName ,jobInfo .exitCode ));
190143 }
144+ return ;
145+ }
146+ String jobInitiator = attached .getSubjectUsernames ().get (0 );
147+ if (!attachedUser .equals (jobInitiator )) {
148+ ar .setActionExitCode (ActionReport .ExitCode .FAILURE );
149+ ar .setMessage (strings .getLocalString ("user.not.authorized" ,
150+ "User {0} not authorized to attach to job {1}" , attachedUser , jobID ));
151+ return ;
152+ }
153+ //Very sensitive locking part
154+ AdminCommandEventBroker <?> attachedBroker = attached .getEventBroker ();
155+ CommandProgress commandProgress = attached .getCommandProgress ();
156+ if (commandProgress == null ) {
157+ synchronized (attachedBroker ) {
158+ onAdminCommandEvent (AdminCommandStateImpl .EVENT_STATE_CHANGED , attached );
159+ attachedBroker .registerListener (".*" , this );
160+ }
161+ } else {
162+ synchronized (commandProgress ) {
163+ onAdminCommandEvent (AdminCommandStateImpl .EVENT_STATE_CHANGED , attached );
164+ onAdminCommandEvent (CommandProgress .EVENT_PROGRESSSTATUS_STATE , attached .getCommandProgress ());
165+ attachedBroker .registerListener (".*" , this );
166+ }
167+ }
168+ synchronized (attached ) {
169+ while (PREPARED .equals (attached .getState ()) || RUNNING .equals (attached .getState ())
170+ || RUNNING_RETRYABLE .equals (attached .getState ())) {
171+ try {
172+ LOG .log (WARNING , "Waiting for job {0}!" , attached );
173+ attached .wait ();
174+ } catch (InterruptedException e ) {
175+ LOG .log (WARNING , "Job {0} interrupted!" );
176+ }
177+ }
178+ if (COMPLETED .equals (attached .getState ()) || REVERTED .equals (attached .getState ())) {
179+ String commandUser = attached .getSubjectUsernames ().get (0 );
180+ //In most cases if the user who attaches to the command is the same
181+ //as one who started it then purge the job once it is completed
182+ if (attachedUser .equals (commandUser ) && attached .isOutboundPayloadEmpty ()) {
183+ purgeJob (attached .getId ());
184+ }
185+ ar .setActionExitCode (attached .getActionReport ().getActionExitCode ());
186+ ar .appendMessage (strings .getLocalString ("attach.finished" , "Command {0} executed with status {1}" ,
187+ attached .getName (), attached .getActionReport ().getActionExitCode ()));
188+ }
191189 }
192190 }
193191
0 commit comments