001    // Copyright(c) 2015 POSCO ICT
002    // Change history
003    // 2015-07-10 / 1.1.0 / 
004    package com.poscoict.app.job;
005    
006    import java.lang.management.ManagementFactory;
007    import java.lang.reflect.InvocationTargetException;
008    import java.lang.reflect.Method;
009    import java.sql.Connection;
010    import java.sql.PreparedStatement;
011    import java.sql.SQLException;
012    import java.util.Date;
013    import java.util.List;
014    import java.util.Map;
015    
016    import javax.sql.DataSource;
017    
018    import org.apache.commons.dbcp.BasicDataSource;
019    import org.slf4j.Logger;
020    import org.slf4j.LoggerFactory;
021    import org.springframework.context.ApplicationContext;
022    import org.springframework.context.support.ClassPathXmlApplicationContext;
023    import org.springframework.jdbc.datasource.DataSourceUtils;
024    import org.springframework.jdbc.support.JdbcUtils;
025    
026    import com.poscoict.glueframework.biz.control.GlueBizControlConstants;
027    import com.poscoict.glueframework.biz.control.GlueBizProvider;
028    import com.poscoict.glueframework.context.GlueContext;
029    import com.poscoict.glueframework.context.GlueDefaultContext;
030    
031    /**
032     * Main Ŭ·¡½º.
033     * 
034     * <pre>
035     * java [-option] com.poscoict.app.job.GlueSimpleJob [args..] 
036     * ÇüÅ·ΠGlueSimpleJob Ŭ·¡½º¸¦ ½ÇÇàÇÑ´Ù.
037     * 
038     * [args..] ºÎºÐÀÇ Ã¹¹ø°´Â history id, µÎ¹ø°´Â ½ÇÇàÀ¯Çü, ¼¼¹ø°ºÎÅÍ´Â »ç¿ëÀÚ data·Î ±¸¼ºÇÑ´Ù. 
039     * <xmp>
040     * java [-option] com.poscoict.app.job.GlueSimpleJob -1 ServiceName=job001-service@S userKey=userData@S
041     * java [-option] com.poscoict.app.job.GlueSimpleJob -1 className=sample.job.SamplePgm@S userKey=userData@S
042     * </xmp>
043     * </pre>
044     */
045    public class GlueSimpleJob
046    {
047        static ApplicationContext applicationContext = null;
048        static Logger logger = LoggerFactory.getLogger( GlueSimpleJob.class );
049    
050        public static void main( String args[] )
051        {
052            logger.info( "GlueSimpleJob version : {}", JobConstants.VERSION );
053            boolean isLocalTest = args != null && args.length > 0 && args[0] != null && "-1".equals( args[0] );
054            if ( !isLocalTest )
055            {
056                BasicDataSource dataSource = null;
057                Connection connection = null;
058                try
059                {
060                    applicationContext = new ClassPathXmlApplicationContext( "applicationContext-job.xml" );
061                    dataSource = applicationContext.getBean( "dataSource", BasicDataSource.class );
062                    connection = DataSourceUtils.getConnection( dataSource );
063                    String databaseProductName = connection.getMetaData().getDatabaseProductName().toLowerCase();
064                    if ( databaseProductName.indexOf( "oracle" ) >= 0 )
065                    {
066                        dataSource.addConnectionProperty( "v$session.program", "GlueSimpleJob ver." + JobConstants.VERSION );
067                        // dataSource.addConnectionProperty( "v$session.process", "GlueSimpleJob-java" );
068                        // dataSource.addConnectionProperty( "v$session.terminal", "GlueSimpleJob-terminal" );
069                        // dataSource.addConnectionProperty( "v$session.client_info", "GlueSimpleJob-client" );
070                    } else if ( databaseProductName.indexOf( "postgresql" ) >= 0 || databaseProductName.indexOf( "enterprisedb" ) >= 0 )
071                    {
072                        dataSource.addConnectionProperty( "ApplicationName", "GlueSimpleJob ver." + JobConstants.VERSION );
073                    } else
074                    {
075                        logger.warn( "not support - {}", databaseProductName );
076                    }
077                    if ( databaseProductName.indexOf( "oracle" ) >= 0 )
078                    {
079                        dataSource.addConnectionProperty( "v$session.program", "GlueSimpleJob ver." + JobConstants.VERSION );
080                    }
081                } catch ( Throwable t )
082                {
083                    logger.error( "Throwable", t );
084                    t.printStackTrace();
085                    return;
086                } finally
087                {
088                    DataSourceUtils.releaseConnection( connection, dataSource );
089                }
090            }
091    
092            String name = ManagementFactory.getRuntimeMXBean().getName();
093            String pid = name.substring( 0, name.indexOf( "@" ) );
094            logger.info( "RuntimeMXBean Name : {}, {}", name, pid );
095            if ( logger.isTraceEnabled() )
096            {
097                logger.trace( "BootClassPath : {}", ManagementFactory.getRuntimeMXBean().getBootClassPath() );
098                logger.trace( "ClassPath : {}", ManagementFactory.getRuntimeMXBean().getClassPath() );
099                logger.trace( "LibraryPath : {}", ManagementFactory.getRuntimeMXBean().getLibraryPath() );
100                logger.trace( "ManagementSpecVersion : {}", ManagementFactory.getRuntimeMXBean().getManagementSpecVersion() );
101                logger.trace( "SpecName : {}", ManagementFactory.getRuntimeMXBean().getSpecName() );
102                logger.trace( "SpecVendor : {}", ManagementFactory.getRuntimeMXBean().getSpecVendor() );
103                logger.trace( "SpecVersion : {}", ManagementFactory.getRuntimeMXBean().getSpecVersion() );
104                logger.trace( "StartTime : {}", ManagementFactory.getRuntimeMXBean().getStartTime() );
105                logger.trace( "Uptime : {}", ManagementFactory.getRuntimeMXBean().getUptime() );
106                logger.trace( "VmName : {}", ManagementFactory.getRuntimeMXBean().getVmName() );
107                logger.trace( "VmVendor : {}", ManagementFactory.getRuntimeMXBean().getVmVendor() );
108                logger.trace( "VmVersion : {}", ManagementFactory.getRuntimeMXBean().getVmVersion() );
109                logger.trace( "SystemProperties : {}", ManagementFactory.getRuntimeMXBean().getSystemProperties() );
110                logger.trace( "BootClassPathSupported : {}", ManagementFactory.getRuntimeMXBean().isBootClassPathSupported() );
111                logger.trace( "InputArguments : {}", ManagementFactory.getRuntimeMXBean().getInputArguments() );
112                List<String> arguements = ManagementFactory.getRuntimeMXBean().getInputArguments();
113                for ( String string : arguements )
114                {
115                    logger.trace( "InputArgument : {}", string );
116                }
117            }
118            if ( !isLocalTest )
119                GlueSimpleJob.updateStartTime( args[0], pid );
120            long start = System.currentTimeMillis();
121            GlueContext ctx = new GlueDefaultContext();
122            String requestId = null;
123            try
124            {
125                requestId = args[0];
126                if ( logger.isTraceEnabled() )
127                {
128                    Map<String, String> env = System.getenv();
129                    logger.trace( "{}", env );
130                    logger.trace( "" );
131                    logger.trace( "{}", System.getProperties() );
132                    logger.trace( "" );
133                    logger.trace( "" );
134                }
135    
136                logger.info( "RequestID:[{}] StartTime[{}]", requestId, new Date( start ) );
137    
138                ctx.put( JobConstants.JOB_REQUEST_ID, requestId );
139    
140                for ( int i = 1; i < args.length; i++ )
141                {
142                    String arg = args[i];
143                    logger.trace( "{}", arg );
144                    // K:Keyword;S:String;B:boolean;I:Integer;L:Long;D:Double;F:Float
145                    if ( arg.contains( "=" ) )
146                    {
147                        String s[] = arg.split( "=" );
148                        if ( arg.startsWith( "\"" ) && arg.endsWith( "\"" ) )
149                        {
150                            String tmp = arg.substring( 1, arg.length() - 1 );
151                            logger.trace( "{}", tmp );
152                            s = tmp.split( "=" );
153                        }
154                        if ( s[1].contains( "@" ) )
155                        {
156                            int idx = s[1].lastIndexOf( "@" );
157                            String value = s[1].substring( 0, idx );
158                            if ( s[1].endsWith( "S" ) )
159                            {
160                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? "" : value );
161                            } else if ( s[1].endsWith( "B" ) )
162                            {
163                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : Boolean.valueOf( value ) );
164                            } else if ( s[1].endsWith( "I" ) )
165                            {
166                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Integer( value ) );
167                            } else if ( s[1].endsWith( "L" ) )
168                            {
169                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Long( value ) );
170                            } else if ( s[1].endsWith( "D" ) )
171                            {
172                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Double( value ) );
173                            } else if ( s[1].endsWith( "F" ) )
174                            {
175                                ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Float( value ) );
176                            }
177                        } else
178                        {
179                            ctx.put( s[0], s[1] );
180                        }
181                    } else
182                    {
183                        logger.error( "ignore {}", arg );
184                    }
185                }
186                logger.info( "{}", ctx );
187    
188                if ( ctx.containsKey( GlueBizControlConstants.SERVICE_NAME ) )
189                {
190                    try
191                    {
192                        GlueBizProvider.getController().doAction( ctx );
193                    } catch ( Throwable t )
194                    {
195                        if ( ctx.getException() != null )
196                        {
197                            // BeanCreationException µî GlueService ½ÇÇà Àü¿¡ ¹ß»ýµÈ ¿¡·¯¸¦ ó¸®Çϱâ À§ÇÔ.
198                            ctx.setException( t );
199                        } else
200                        {
201                            logger.error( "unknwon error", t );
202                        }
203                        t.printStackTrace();
204                    }
205                } else if ( ctx.containsKey( "className" ) )
206                {
207                    try
208                    {
209                        Object clz = Thread.currentThread().getContextClassLoader().loadClass( (String) ctx.get( "className" ) ).newInstance();
210                        Method method = clz.getClass().getMethod( "runProgram", new Class[] { GlueContext.class } );
211                        method.invoke( clz, new Object[] { ctx } );
212                        if ( ctx.getException() != null )
213                        {
214                            logger.error( "UserException", ctx.getException() );
215                            ctx.getException().printStackTrace();
216                        }
217                        // ctx.getException();
218                    } catch ( InstantiationException e )
219                    {
220                        ctx.setException( e );
221                        logger.error( "InstantiationException", e );
222                    } catch ( IllegalAccessException e )
223                    {
224                        ctx.setException( e );
225                        logger.error( "IllegalAccessException", e );
226                    } catch ( ClassNotFoundException e )
227                    {
228                        ctx.setException( e );
229                        logger.error( "ClassNotFoundException", e );
230                    } catch ( SecurityException e )
231                    {
232                        ctx.setException( e );
233                        logger.error( "SecurityException", e );
234                    } catch ( NoSuchMethodException e )
235                    {
236                        ctx.setException( e );
237                        logger.error( "NoSuchMethodException", e );
238                    } catch ( IllegalArgumentException e )
239                    {
240                        ctx.setException( e );
241                        logger.error( "IllegalArgumentException", e );
242                    } catch ( InvocationTargetException e )
243                    {
244                        ctx.setException( e );
245                        logger.error( "InvocationTargetException", e );
246                    } catch ( Throwable t )
247                    {
248                        ctx.setException( t );
249                        logger.error( "UserException", t );
250                    }
251                } else
252                {
253                    ctx.setException( new Exception( "Service is Null!" ) );
254                    logger.info( "Service is Null!" );
255                }
256    
257            } catch ( Exception e )
258            {
259                logger.error( "Exception", e );
260                e.printStackTrace();
261            } catch ( Throwable t )
262            {
263                logger.error( "Throwable", t );
264                t.printStackTrace();
265            } finally
266            {
267                long end = System.currentTimeMillis();
268                if ( !isLocalTest )
269                    GlueSimpleJob.updateEndTime( args[0], end - start, ctx.getException() );
270                logger.info( "RequestID:[{}] EndTime[{}] RunTime:[{}]", requestId, new Date( end ), end - start );
271            }
272            System.exit( 0 );
273        }
274    
275        private static void updateEndTime( String id, long runtime, Throwable throwable )
276        {
277            try
278            {
279                if ( "-1".equals( id ) )
280                {
281                    return;
282                }
283                DataSource ds = applicationContext.getBean( "dataSource", DataSource.class );
284                logger.debug( "{}", JobConstants.SQL_PGM_END );
285                logger.trace( "{}", runtime );
286                logger.trace( "{}", throwable == null ? "END" : "ERROR" );
287                logger.trace( "{}", id );
288                Connection con = null;
289                PreparedStatement ps = null;
290                con = DataSourceUtils.getConnection( ds );
291                try
292                {
293                    ps = con.prepareStatement( JobConstants.SQL_PGM_END );
294                    ps.setObject( 1, runtime );
295                    ps.setObject( 2, throwable == null ? "END" : "ERROR" );
296                    ps.setObject( 3, new Long( id ) );
297                    ps.executeUpdate();
298                    con.commit();
299                } catch ( SQLException e )
300                {
301                    logger.error( "fail to executeUpdate", e );
302                } finally
303                {
304                    JdbcUtils.closeStatement( ps );
305                    DataSourceUtils.releaseConnection( con, ds );
306                }
307            } catch ( Exception e )
308            {
309                logger.error( "fail to getConnection", e );
310            } catch ( Throwable t )
311            {
312                logger.error( "fail to getConnection", t );
313            }
314        }
315    
316        private static void updateStartTime( String id, String pid )
317        {
318            try
319            {
320                if ( "-1".equals( id ) )
321                {
322                    return;
323                }
324                DataSource ds = applicationContext.getBean( "dataSource", DataSource.class );
325                logger.debug( "{}", JobConstants.SQL_PGM_START );
326                logger.trace( "{}", "RUNNING" );
327                logger.trace( "{}", pid );
328                logger.trace( "{}", id );
329    
330                Connection con = null;
331                PreparedStatement ps = null;
332                con = DataSourceUtils.getConnection( ds );
333                try
334                {
335                    ps = con.prepareStatement( JobConstants.SQL_PGM_START );
336                    ps.setObject( 1, "RUNNING" );
337                    ps.setObject( 2, new Integer( pid ) );
338                    ps.setObject( 3, new Long( id ) );
339                    ps.executeUpdate();
340                    con.commit();
341                } catch ( SQLException e )
342                {
343                    logger.error( "fail to executeUpdate", e );
344                } catch ( Exception e )
345                {
346                    logger.error( "fail to getConnection", e );
347                } catch ( Throwable t )
348                {
349                    logger.error( "fail to getConnection", t );
350                } finally
351                {
352                    JdbcUtils.closeStatement( ps );
353                    DataSourceUtils.releaseConnection( con, ds );
354                }
355            } catch ( Exception e )
356            {
357                logger.error( "fail to getConnection", e );
358            } catch ( Throwable t )
359            {
360                logger.error( "fail to getConnection", t );
361            }
362        }
363    }