001    /**
002     * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003     * Licensed under the Apache License, Version 2.0 (the "License");
004     * you may not use this file except in compliance with the License.
005     * You may obtain a copy of the License at
006     *
007     *   http://www.apache.org/licenses/LICENSE-2.0
008     *
009     *  Unless required by applicable law or agreed to in writing, software
010     *  distributed under the License is distributed on an "AS IS" BASIS,
011     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012     *  See the License for the specific language governing permissions and
013     *  limitations under the License. See accompanying LICENSE file.
014     */
015    package org.apache.oozie.command.coord;
016    
017    import java.io.IOException;
018    import java.io.StringReader;
019    import java.net.HttpURLConnection;
020    import java.net.URL;
021    
022    import org.apache.hadoop.conf.Configuration;
023    import org.apache.oozie.CoordinatorActionBean;
024    import org.apache.oozie.ErrorCode;
025    import org.apache.oozie.client.OozieClient;
026    import org.apache.oozie.command.CommandException;
027    import org.apache.oozie.command.PreconditionException;
028    import org.apache.oozie.util.LogUtils;
029    import org.apache.oozie.util.ParamChecker;
030    import org.apache.oozie.util.XConfiguration;
031    import org.apache.oozie.util.XLog;
032    
033    /**
034     * This class will send the notification for the coordinator action
035     */
036    public class CoordActionNotificationXCommand extends CoordinatorXCommand<Void> {
037    
038        private final CoordinatorActionBean actionBean;
039        private static final String STATUS_PATTERN = "\\$status";
040        private static final String ACTION_ID_PATTERN = "\\$actionId";
041    
042        private int retries = 0;
043    
044        public CoordActionNotificationXCommand(CoordinatorActionBean actionBean) {
045            super("coord_action_notification", "coord_action_notification", 0);
046            ParamChecker.notNull(actionBean, "Action Bean");
047            this.actionBean = actionBean;
048        }
049    
050        /* (non-Javadoc)
051         * @see org.apache.oozie.command.XCommand#execute()
052         */
053        @Override
054        protected Void execute() throws CommandException {
055            LOG.info("STARTED Coordinator Notification actionId=" + actionBean.getId() + " : " + actionBean.getStatus());
056            Configuration conf;
057            try {
058                conf = new XConfiguration(new StringReader(actionBean.getRunConf()));
059            }
060            catch (IOException e1) {
061                LOG.warn("Configuration parse error. read from DB :" + actionBean.getRunConf());
062                throw new CommandException(ErrorCode.E1005, e1.getMessage(), e1);
063            }
064            String url = conf.get(OozieClient.COORD_ACTION_NOTIFICATION_URL);
065            if (url != null) {
066                url = url.replaceAll(ACTION_ID_PATTERN, actionBean.getId());
067                url = url.replaceAll(STATUS_PATTERN, actionBean.getStatus().toString());
068                LOG.debug("Notification URL :" + url);
069                try {
070                    URL urlObj = new URL(url);
071                    HttpURLConnection urlConn = (HttpURLConnection) urlObj.openConnection();
072                    if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
073                        handleRetry(url);
074                    }
075                }
076                catch (IOException ex) {
077                    handleRetry(url);
078                }
079            }
080            else {
081                LOG.info("No Notification URL is defined. Therefore nothing to notify for job " + actionBean.getJobId()
082                        + " action ID " + actionBean.getId());
083            }
084            LOG.info("ENDED Coordinator Notification actionId=" + actionBean.getId());
085            return null;
086        }
087    
088        /**
089         * This method handles the retry for the coordinator action.
090         *
091         * @param url This is the URL where the notification has to be sent.
092         */
093        private void handleRetry(String url) {
094            if (retries < 3) {
095                retries++;
096                this.resetUsed();
097                queue(this, 60 * 1000);
098            }
099            else {
100                LOG.warn(XLog.OPS, "could not send notification [{0}]", url);
101            }
102        }
103    
104        /* (non-Javadoc)
105         * @see org.apache.oozie.command.XCommand#getEntityKey()
106         */
107        @Override
108        protected String getEntityKey() {
109            return actionBean.getId();
110        }
111    
112        /* (non-Javadoc)
113         * @see org.apache.oozie.command.XCommand#isLockRequired()
114         */
115        @Override
116        protected boolean isLockRequired() {
117            return false;
118        }
119    
120        /* (non-Javadoc)
121         * @see org.apache.oozie.command.XCommand#loadState()
122         */
123        @Override
124        protected void loadState() throws CommandException {
125            LogUtils.setLogInfo(actionBean, logInfo);
126        }
127    
128        /* (non-Javadoc)
129         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
130         */
131        @Override
132        protected void verifyPrecondition() throws CommandException, PreconditionException {
133        }
134    }