When securing a web application there are few options for authentication and authorization of user/roles. You could write your custom logic, use container managed security, or use 3rd part libraries, or augment container managed security with custom logic.
Custom Security: Custom security is implemented by writing programming logic. For a pure Struts2 app (Where every url of the web application is served by Struts actions), typically user is authenticated using a custom HTML form backed by a custom LoginAction. LoginAction will validated username/password and then store the user information in session variable. This user/role information stored in session can be used control the logic for what URL/actions can be accessed by user. You can write a Struts2 interceptor and have every single request for struts2 resource go through this interceptor. When user tries to access a resource in the application, this interceptor will check if user is not logged by looking at certain data in user session. If data is not found user can redirected to login action. If user is logged in then you can check the role to make sure user has access to the resource, once the action is executed, you can use the user role information in view code (JSPs or other ) to hide/show certain section of view.
Disadvantage of above approach is is that only struts actions are protected. Another approach will be to write a Servlet filter instead of a struts Interceptor. Other disadvantage is you will end up with lot of logic for protecting different url for various roles. You may write code to read a custom configuration file.
Following is sample code
struts.xml
---------------
<package extends="struts-default">
<interceptors>
<interceptor name="login" class="mypkg.AuthenticationInterceptor"/>
<interceptor-stack name="intStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="intStack"/>
Login form
---------------
<s:form action="login">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
LoginAction
----------------
public class LoginAction {
private User user;
private String username;
private String password;
public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();
if (username == null) {
return "login";
}
user = yourDAO.getUser(username, password);
if (user != null) {
session.put("user", user);
return SUCCESS;
}
else {
return "login";
}
}
public void setUsername(String username){
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword() {
return password;
}
}
Interceptor code
----------------------
public class AuthenticationInterceptor implements Interceptor {
public String intercept(ActionInvocation invocation) throws Exception {
Map session = ActionContext.getContext().getSession();
//Check by looking at user's http session for certain data which you
// If not logged in redirect user to login.action
if (!session.containsKey("user") && !ActionContext.getContext().getName().equals("login")) {
return "login";
}
// If user is logged in then vcheck if user has access to requested url
String result = invocation.invoke();
return result;
}
}
Container managed security + Custom security: Servlet specification provides declarative security, access to web resources can be defined in web.xml. Once user is authenticated application servlet API could be used to access authenticated user / role information. Struts2 action can also be restricted to certain roles declarative style. One drawback is Roles information needs to be maintained in web.xml, If your application creates roles dynamically, new roles have to be also specified in web.xml (Needs rebuilding war file/application restart).
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Role required to see admin pages.</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Role with read only.</description>
<role-name>reader</role-name>
</security-role>
For autheticating form authentication can be used with a jsp specified in web.xml, the jsp includes a form action j_security_check. username/password are validated against the realm specified in web.xml. Realm represents the source of username/password and associated roles. There are a wide variety of Realms (JDBC, JNDI, xml file, Datasource) which are specific to servlet containers. For a web application deployed in Tomcat Realm is specified in context.xml under META-INF/ direcotory
<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login2.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Login form
----------
<s:form action="j_security_check">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="j_username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="j_password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
META-INF/context.xml, login action will be validated against following Realm
-------------------------------------------------------------------------
<Context>
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://mydbserver/mydb_test2"
connectionName="myuser" connectionPassword="mypassword"
userTable="users" userNameCol="email"
userCredCol="password" digest="MD5"
userRoleTable="user_roles" roleNameCol="name"/>
</Context>
Above setup will provide for authentication and authorization for URL in web applications.
If you application requires further restrictions on struts Actions based on user roles, roles interceptor could be used and security could be declared in struts.xml.
Any further customization could be programmed by writing additional struts interceptors or servlet filters. Following is an example of custom interceptor where a different struts result/view is presented to user based on role.
public class ReaderViewInterceptor implements Interceptor{
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map resultsMap = invocation.getProxy().getConfig().getResults();
if( ServletActionContext.getRequest().isUserInRole("Reader") ) {
invocation.setResultCode("readonly_" + resultCode);
}
}
});
String result = invocation.invoke();
return result;
}
}
Saturday, July 18, 2009
Web App + Security + Struts2
When securing a web application there are few options for authentication and authorization of user/roles. You could write your custom logic, use container managed security, or use 3rd part libraries, or augment container managed security with custom logic.
Custom Security: Custom security is implemented by writing programming logic. For a pure Struts2 app (Where every url of the web application is served by Struts actions), typically user is authenticated using a custom HTML form backed by a custom LoginAction. LoginAction will validated username/password and then store the user information in session variable. This user/role information stored in session can be used control the logic for what URL/actions can be accessed by user. You can write a Struts2 interceptor and have every single request for struts2 resource go through this interceptor. When user tries to access a resource in the application, this interceptor will check if user is not logged by looking at certain data in user session. If data is not found user can redirected to login action. If user is logged in then you can check the role to make sure user has access to the resource, once the action is executed, you can use the user role information in view code (JSPs or other ) to hide/show certain section of view.
Disadvantage of above approach is is that only struts actions are protected. Another approach will be to write a Servlet filter instead of a struts Interceptor. Other disadvantage is you will end up with lot of logic for protecting different url for various roles. You may write code to read a custom configuration file.
Following is sample code
struts.xml
---------------
<package extends="struts-default">
<interceptors>
<interceptor name="login" class="mypkg.AuthenticationInterceptor"/>
<interceptor-stack name="intStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="intStack"/>
Login form
---------------
<s:form action="login">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
LoginAction
----------------
public class LoginAction {
private User user;
private String username;
private String password;
public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();
if (username == null) {
return "login";
}
user = yourDAO.getUser(username, password);
if (user != null) {
session.put("user", user);
return SUCCESS;
}
else {
return "login";
}
}
public void setUsername(String username){
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword() {
return password;
}
}
Interceptor code
----------------------
public class AuthenticationInterceptor implements Interceptor {
public String intercept(ActionInvocation invocation) throws Exception {
Map session = ActionContext.getContext().getSession();
//Check by looking at user's http session for certain data which you
// If not logged in redirect user to login.action
if (!session.containsKey("user") && !ActionContext.getContext().getName().equals("login")) {
return "login";
}
// If user is logged in then vcheck if user has access to requested url
String result = invocation.invoke();
return result;
}
}
Container managed security + Custom security: Servlet specification provides declarative security, access to web resources can be defined in web.xml. Once user is authenticated application servlet API could be used to access authenticated user / role information. Struts2 action can also be restricted to certain roles declarative style. One drawback is Roles information needs to be maintained in web.xml, If your application creates roles dynamically, new roles have to be also specified in web.xml (Needs rebuilding war file/application restart).
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Role required to see admin pages.</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Role with read only.</description>
<role-name>reader</role-name>
</security-role>
For autheticating form authentication can be used with a jsp specified in web.xml, the jsp includes a form action j_security_check. username/password are validated against the realm specified in web.xml. Realm represents the source of username/password and associated roles. There are a wide variety of Realms (JDBC, JNDI, xml file, Datasource) which are specific to servlet containers. For a web application deployed in Tomcat Realm is specified in context.xml under META-INF/ direcotory
<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login2.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Login form
----------
<s:form action="j_security_check">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="j_username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="j_password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
META-INF/context.xml, login action will be validated against following Realm
-------------------------------------------------------------------------
<Context>
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://mydbserver/mydb_test2"
connectionName="myuser" connectionPassword="mypassword"
userTable="users" userNameCol="email"
userCredCol="password" digest="MD5"
userRoleTable="user_roles" roleNameCol="name"/>
</Context>
Above setup will provide for authentication and authorization for URL in web applications.
If you application requires further restrictions on struts Actions based on user roles, roles interceptor could be used and security could be declared in struts.xml.
Any further customization could be programmed by writing additional struts interceptors or servlet filters. Following is an example of custom interceptor where a different struts result/view is presented to user based on role.
public class ReaderViewInterceptor implements Interceptor{
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map resultsMap = invocation.getProxy().getConfig().getResults();
if( ServletActionContext.getRequest().isUserInRole("Reader") ) {
invocation.setResultCode("readonly_" + resultCode);
}
}
});
String result = invocation.invoke();
return result;
}
}
Custom Security: Custom security is implemented by writing programming logic. For a pure Struts2 app (Where every url of the web application is served by Struts actions), typically user is authenticated using a custom HTML form backed by a custom LoginAction. LoginAction will validated username/password and then store the user information in session variable. This user/role information stored in session can be used control the logic for what URL/actions can be accessed by user. You can write a Struts2 interceptor and have every single request for struts2 resource go through this interceptor. When user tries to access a resource in the application, this interceptor will check if user is not logged by looking at certain data in user session. If data is not found user can redirected to login action. If user is logged in then you can check the role to make sure user has access to the resource, once the action is executed, you can use the user role information in view code (JSPs or other ) to hide/show certain section of view.
Disadvantage of above approach is is that only struts actions are protected. Another approach will be to write a Servlet filter instead of a struts Interceptor. Other disadvantage is you will end up with lot of logic for protecting different url for various roles. You may write code to read a custom configuration file.
Following is sample code
struts.xml
---------------
<package extends="struts-default">
<interceptors>
<interceptor name="login" class="mypkg.AuthenticationInterceptor"/>
<interceptor-stack name="intStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="intStack"/>
Login form
---------------
<s:form action="login">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
LoginAction
----------------
public class LoginAction {
private User user;
private String username;
private String password;
public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();
if (username == null) {
return "login";
}
user = yourDAO.getUser(username, password);
if (user != null) {
session.put("user", user);
return SUCCESS;
}
else {
return "login";
}
}
public void setUsername(String username){
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword() {
return password;
}
}
Interceptor code
----------------------
public class AuthenticationInterceptor implements Interceptor {
public String intercept(ActionInvocation invocation) throws Exception {
Map session = ActionContext.getContext().getSession();
//Check by looking at user's http session for certain data which you
// If not logged in redirect user to login.action
if (!session.containsKey("user") && !ActionContext.getContext().getName().equals("login")) {
return "login";
}
// If user is logged in then vcheck if user has access to requested url
String result = invocation.invoke();
return result;
}
}
Container managed security + Custom security: Servlet specification provides declarative security, access to web resources can be defined in web.xml. Once user is authenticated application servlet API could be used to access authenticated user / role information. Struts2 action can also be restricted to certain roles declarative style. One drawback is Roles information needs to be maintained in web.xml, If your application creates roles dynamically, new roles have to be also specified in web.xml (Needs rebuilding war file/application restart).
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Role required to see admin pages.</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Role with read only.</description>
<role-name>reader</role-name>
</security-role>
For autheticating form authentication can be used with a jsp specified in web.xml, the jsp includes a form action j_security_check. username/password are validated against the realm specified in web.xml. Realm represents the source of username/password and associated roles. There are a wide variety of Realms (JDBC, JNDI, xml file, Datasource) which are specific to servlet containers. For a web application deployed in Tomcat Realm is specified in context.xml under META-INF/ direcotory
<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login2.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Login form
----------
<s:form action="j_security_check">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="j_username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="j_password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>
META-INF/context.xml, login action will be validated against following Realm
-------------------------------------------------------------------------
<Context>
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://mydbserver/mydb_test2"
connectionName="myuser" connectionPassword="mypassword"
userTable="users" userNameCol="email"
userCredCol="password" digest="MD5"
userRoleTable="user_roles" roleNameCol="name"/>
</Context>
Above setup will provide for authentication and authorization for URL in web applications.
If you application requires further restrictions on struts Actions based on user roles, roles interceptor could be used and security could be declared in struts.xml.
Any further customization could be programmed by writing additional struts interceptors or servlet filters. Following is an example of custom interceptor where a different struts result/view is presented to user based on role.
public class ReaderViewInterceptor implements Interceptor{
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map
if( ServletActionContext.getRequest().isUserInRole("Reader") ) {
invocation.setResultCode("readonly_" + resultCode);
}
}
});
String result = invocation.invoke();
return result;
}
}
Tuesday, June 30, 2009
MySQL InnoDB lock
Recently I had to extract data from a number of large tables (MySql 5.0 InnoDB tables). Given the size of tables and number of joins, I used TEMP tables and stored procedure. When pushing data into temp tables I ran into locks on underlying SELECT tables. These queries were being run on a slave copy of MySQL replication. Lock on the select table were causing replication UPDATE/INSERT queries to time out and crash replication.
It turned out "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." was locking large tables (InnoDB tables), even after specifying appropriate TRANSACTION ISOLATION LEVEL of READ COMMITTED.
MySQL documentation says the tables won't be locked, but they do get locked on 5.0.
"INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record without a gap lock on each row inserted into T. If innodb_locks_unsafe_for_binlog is enabled or the transaction isolation level is READ COMMITTED, InnoDB does the search on S as a consistent read (no locks)"
An ugly workaround was to use "SELECT INTO OUTFILE". Once you write to OUTFILE, you need to import it back in DB using LOAD DATE INFILE. It turns out you can not use LOAD DATA INFILE inside a stored procedure, so I had to fall back to Perl script to do the job.
Suggestions to MySQL.
1) Provide ability to ISSUE "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." without locking tables when an apporpriate transaction level is specified. This probably is already fixed in 5.1.
2) Allow DATA LOAD INFILE from stored procedures.
It turned out "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." was locking large tables (InnoDB tables), even after specifying appropriate TRANSACTION ISOLATION LEVEL of READ COMMITTED.
MySQL documentation says the tables won't be locked, but they do get locked on 5.0.
"INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record without a gap lock on each row inserted into T. If innodb_locks_unsafe_for_binlog is enabled or the transaction isolation level is READ COMMITTED, InnoDB does the search on S as a consistent read (no locks)"
An ugly workaround was to use "SELECT INTO OUTFILE". Once you write to OUTFILE, you need to import it back in DB using LOAD DATE INFILE. It turns out you can not use LOAD DATA INFILE inside a stored procedure, so I had to fall back to Perl script to do the job.
Suggestions to MySQL.
1) Provide ability to ISSUE "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." without locking tables when an apporpriate transaction level is specified. This probably is already fixed in 5.1.
2) Allow DATA LOAD INFILE from stored procedures.
MySQL InnoDB lock
Recently I had to extract data from a number of large tables (MySql 5.0 InnoDB tables). Given the size of tables and number of joins, I used TEMP tables and stored procedure. When pushing data into temp tables I ran into locks on underlying SELECT tables. These queries were being run on a slave copy of MySQL replication. Lock on the select table were causing replication UPDATE/INSERT queries to time out and crash replication.
It turned out "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." was locking large tables (InnoDB tables), even after specifying appropriate TRANSACTION ISOLATION LEVEL of READ COMMITTED.
MySQL documentation says the tables won't be locked, but they do get locked on 5.0.
"INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record without a gap lock on each row inserted into T. If innodb_locks_unsafe_for_binlog is enabled or the transaction isolation level is READ COMMITTED, InnoDB does the search on S as a consistent read (no locks)"
An ugly workaround was to use "SELECT INTO OUTFILE". Once you write to OUTFILE, you need to import it back in DB using LOAD DATE INFILE. It turns out you can not use LOAD DATA INFILE inside a stored procedure, so I had to fall back to Perl script to do the job.
Suggestions to MySQL.
1) Provide ability to ISSUE "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." without locking tables when an apporpriate transaction level is specified. This probably is already fixed in 5.1.
2) Allow DATA LOAD INFILE from stored procedures.
It turned out "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." was locking large tables (InnoDB tables), even after specifying appropriate TRANSACTION ISOLATION LEVEL of READ COMMITTED.
MySQL documentation says the tables won't be locked, but they do get locked on 5.0.
"INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record without a gap lock on each row inserted into T. If innodb_locks_unsafe_for_binlog is enabled or the transaction isolation level is READ COMMITTED, InnoDB does the search on S as a consistent read (no locks)"
An ugly workaround was to use "SELECT INTO OUTFILE". Once you write to OUTFILE, you need to import it back in DB using LOAD DATE INFILE. It turns out you can not use LOAD DATA INFILE inside a stored procedure, so I had to fall back to Perl script to do the job.
Suggestions to MySQL.
1) Provide ability to ISSUE "INSERT INTO A_TEMP_TABLE select X, Y, Z from LARGE_TABLE1, LARGE_TABLE1 WHERE....." without locking tables when an apporpriate transaction level is specified. This probably is already fixed in 5.1.
2) Allow DATA LOAD INFILE from stored procedures.
Wednesday, April 29, 2009
checked and unchecked exception

Checked Exceptions. These are the exception that must be caught if you call a method that throws Checked exception. A method that may throw such exception, must explicitly declare it in method signature.
Unchecked exceptions: They can be thrown anytime, they not forced to be caught by compiler. Methods do not have to declare that they can throw an unchecked exception. Error and RuntimeException and their subclasses are treated as unchecked exceptions by java compiler.
Exceptions represent errors from which a program can potentially recover.
Exceptions and all its subclasses except RuntimeException are "Checked" exception
if you call a method that throws an exception you must have a catch block or declare your method to throw the exception.
Runtime exceptions should represent errors due to programming error, and a program is not expected recover from such exceptions. A program may catch the exception with Catch block but is not forced to catch it by compiler as Runtime excptions are "uncheck exceptions". Example ArrayIndexOutOfBound, NullPointerException, ClassCastException, NumberFormatException
Error class is also "unchecked exceptions". They represent errors from which program can not recover. Example is OutOfMemoryError.
One should try to reuse existing exception classes. There should be a real good exception to write a new exception class.
Following are commonly used exception. IllegalArgumentException, IllegalStateException, NullPointerException, IndexOutOfBoundsException, ConcurrentModificationException, UnsupportedOperationException.
Exception chaining: wrap an exception in a new one and throw new exception.
Try handling them at lower level.
Document exceptions thrown by a method.
Include detailed error message.
Validate and throw exceptions early on in a method.
Don't ignore exceptions
Reference: Effective Java, 2nd edition.
Monday, March 9, 2009
Wednesday, March 4, 2009
Love and hate regular expressions
I had to look at thousands of lines of perl code packed full of regular expressions (some spanning multiple line). It is not a fun thing. Regular expression are extremely powerful, with power comes responsibility :).
I would use them with the consideration that the code I write will have to maintained by someone else few months/years down the line. I would place a few lines of documentation as to what the code is trying to do. It is very hard to document regular expression, placing a example text as to what RegEx is searching for helps.
If I am writing a one time script that won't be used by anyone else, I would unleash the full power for regular expressions.
Do check out this online tool to test your regular expressions. I can't thank enough the author of this tool. http://www.gskinner.com/RegExr/ , it made writing and testing the regular expression much less stressful.
Another great resource to learn regular expressions is at http://www.regular-expressions.info/engine.html
TODO: ADD cheatsheet of regex below!
I would use them with the consideration that the code I write will have to maintained by someone else few months/years down the line. I would place a few lines of documentation as to what the code is trying to do. It is very hard to document regular expression, placing a example text as to what RegEx is searching for helps.
If I am writing a one time script that won't be used by anyone else, I would unleash the full power for regular expressions.
Do check out this online tool to test your regular expressions. I can't thank enough the author of this tool. http://www.gskinner.com/RegExr/ , it made writing and testing the regular expression much less stressful.
Another great resource to learn regular expressions is at http://www.regular-expressions.info/engine.html
TODO: ADD cheatsheet of regex below!
Subscribe to:
Posts (Atom)