1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package net.sf.michaelo.tomcat.extras.listeners;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.util.Map.Entry;
21  import java.util.Objects;
22  import java.util.Properties;
23  
24  import org.apache.catalina.Context;
25  import org.apache.catalina.Lifecycle;
26  import org.apache.catalina.LifecycleEvent;
27  import org.apache.catalina.LifecycleListener;
28  import org.apache.juli.logging.Log;
29  import org.apache.juli.logging.LogFactory;
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  public class PropertiesRoleMappingListener implements LifecycleListener {
51  
52  	private static final String WEBAPP_RESOURCE_PREFIX = "webapp:";
53  	private static final String CLASSPATH_RESOURCE_PREFIX = "classpath:";
54  
55  	private static final Log logger = LogFactory.getLog(PropertiesRoleMappingListener.class);
56  	private Context context;
57  
58  	private String roleMappingFile = "webapp:/WEB-INF/role-mapping.properties";
59  	private String keyPrefix;
60  
61  	public void setRoleMappingFile(String roleMappingFile) {
62  		this.roleMappingFile = Objects.requireNonNull(roleMappingFile,
63  				"roleMappingFile cannot be null");
64  	}
65  
66  	public void setKeyPrefix(String keyPrefix) {
67  		this.keyPrefix = keyPrefix;
68  	}
69  
70  	@Override
71  	public void lifecycleEvent(LifecycleEvent le) {
72  
73  		if (le.getLifecycle() instanceof Context)
74  			context = (Context) le.getLifecycle();
75  		else
76  			return;
77  
78  		if (le.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
79  			InputStream is;
80  
81  			if (roleMappingFile.startsWith(WEBAPP_RESOURCE_PREFIX)) {
82  				String path = roleMappingFile.substring(WEBAPP_RESOURCE_PREFIX.length());
83  				is = context.getServletContext().getResourceAsStream(path);
84  			} else if (roleMappingFile.startsWith(CLASSPATH_RESOURCE_PREFIX)) {
85  				String path = roleMappingFile.substring(CLASSPATH_RESOURCE_PREFIX.length());
86  				is = context.getLoader().getClassLoader().getResourceAsStream(path);
87  			} else {
88  				is = context.getServletContext().getResourceAsStream(roleMappingFile);
89  			}
90  
91  			if (is == null) {
92  				logger.warn(String.format(
93  						"Role mapping file '%s' not found, no role mapping can be performed",
94  						roleMappingFile));
95  				return;
96  			}
97  
98  			Properties props = new Properties();
99  
100 			try {
101 				props.load(is);
102 			} catch (IOException e) {
103 				logger.error(
104 						String.format("Failed to load role mapping file '%s'", roleMappingFile), e);
105 				return;
106 			} finally {
107 				try {
108 					is.close();
109 					is = null;
110 				} catch (IOException e) {
111 					
112 				}
113 			}
114 
115 			int linkCount = 0;
116 			for (Entry<Object, Object> prop : props.entrySet()) {
117 				String role = (String) prop.getKey();
118 
119 				if (keyPrefix != null) {
120 					if (role.startsWith(keyPrefix))
121 						role = role.substring(keyPrefix.length());
122 					else
123 						continue;
124 				}
125 
126 				String link = (String) prop.getValue();
127 
128 				if (logger.isTraceEnabled())
129 					logger.trace(String.format(
130 							"Successfully linked application role '%s' to technical role '%s'",
131 							role, link));
132 				context.addRoleMapping(role, link);
133 				linkCount++;
134 			}
135 
136 			if (logger.isDebugEnabled())
137 				logger.debug(
138 						String.format("Linked %s application roles to technical roles", linkCount));
139 		}
140 
141 	}
142 
143 }