1 16 package nl.hippo.cms.sitesdirectory; 17 18 import java.io.InputStream ; 19 import java.util.ArrayList ; 20 import java.util.Enumeration ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.Properties ; 26 import java.util.StringTokenizer ; 27 import java.util.regex.Pattern ; 28 import nl.hippo.cms.repositorylocation.RepositoryInformation; 29 import org.apache.avalon.framework.activity.Initializable; 30 import org.apache.avalon.framework.logger.AbstractLogEnabled; 31 import org.apache.avalon.framework.parameters.ParameterException; 32 import org.apache.avalon.framework.parameters.Parameterizable; 33 import org.apache.avalon.framework.parameters.Parameters; 34 import org.apache.avalon.framework.service.ServiceException; 35 import org.apache.avalon.framework.service.ServiceManager; 36 import org.apache.avalon.framework.service.Serviceable; 37 import org.apache.excalibur.source.Source; 38 import org.apache.excalibur.source.SourceResolver; 39 40 90 public class SitesDirectoryImpl extends AbstractLogEnabled 91 implements SitesDirectory, Serviceable, Parameterizable, Initializable 92 { 93 private static final String CONFIGURATION_URI_PARAMETER_NAME = "configurationUri"; 94 95 private static final String DEFAULT_CONFIGURATION_URI = "context://noSites.properties"; 96 97 private static final String SITE_LIST_PROPERTY_NAME = "siteList"; 98 99 private static final String VALID_SITE_ID_REGEX = "^[a-zA-Z]+$"; 100 101 private static final String EDITOR_MARKER_PRIVILEGE_NAMESPACE_URI_PROPERTY_SUFFIX = ".editorMarkerPrivilege.namespaceUri"; 102 103 private static final String EDITOR_MARKER_PRIVILEGE_NAME_PROPERTY_SUFFIX = ".editorMarkerPrivilege.name"; 104 105 private static final String PREVIEW_REPOSITORY_ROLE_NAME = "preview"; 106 107 private static final String LIVE_REPOSITORY_ROLE_NAME = "live"; 108 109 private static final String SITE_NAME_REGEX_PREFIX = "^"; 110 111 private static final String SITE_NAME_REGEX_SUFFIX = "\\.name\\.[a-z][a-z]$"; 112 113 private static final String REPOSITORY_PROPERTY_NAME_PART = ".repository."; 114 115 private static final String HOST_PROPERTY_SUFFIX = "host"; 116 117 private static final String PORT_PROPERTY_SUFFIX = "port"; 118 119 private static final String REALM_PROPERTY_SUFFIX = "realm"; 120 121 private static final String USERNAME_PROPERTY_SUFFIX = "username"; 122 123 private static final String PASSWORD_PROPERTY_SUFFIX = "password"; 124 125 private static final String ROOT_URI_PROPERTY_SUFFIX = "rootUri"; 126 127 private static final String BASE_URI_PROPERTY_SUFFIX = "baseUri"; 128 129 134 private ServiceManager m_serviceManager; 135 136 142 private String m_configurationUri; 143 144 149 private Map m_sites = new HashMap (); 150 151 157 private List m_siteIdsOrder = new ArrayList (); 158 159 164 public SitesDirectoryImpl() 165 { 166 super(); 167 } 168 169 178 public void service(ServiceManager serviceManager) throws ServiceException 179 { 180 m_serviceManager = serviceManager; 181 } 182 183 191 public void parameterize(Parameters params) throws ParameterException 192 { 193 m_configurationUri = params.getParameter(CONFIGURATION_URI_PARAMETER_NAME, 194 DEFAULT_CONFIGURATION_URI); 195 } 196 197 202 public void initialize() throws Exception 203 { 204 Properties properties = new Properties (); 205 Object sourceResolverAsObject = m_serviceManager.lookup(SourceResolver.ROLE); 206 try 207 { 208 if (sourceResolverAsObject instanceof SourceResolver) 209 { 210 SourceResolver sourceResolver = (SourceResolver) sourceResolverAsObject; 211 Source source = sourceResolver.resolveURI(m_configurationUri); 212 try 213 { 214 if (source.exists()) 215 { 216 InputStream input = source.getInputStream(); 217 try 218 { 219 properties.load(input); 220 } 221 finally 222 { 223 input.close(); 224 } 225 } 226 else 227 { 228 throw new IllegalArgumentException ("The properties file specified by '" 229 + m_configurationUri + "' must exist."); 230 } 231 } 232 finally 233 { 234 sourceResolver.release(source); 235 } 236 } 237 } 238 finally 239 { 240 m_serviceManager.release(sourceResolverAsObject); 241 } 242 String siteList = properties.getProperty(SITE_LIST_PROPERTY_NAME); 243 if (siteList != null && !siteList.equals("")) 244 { 245 StringTokenizer siteListTokenizer = new StringTokenizer (siteList, ","); 246 while (siteListTokenizer.hasMoreTokens()) 247 { 248 String siteId = siteListTokenizer.nextToken(); 249 if (!isValidSiteId(siteId)) 250 { 251 throw new IllegalArgumentException ("Site ID '" + siteId + "' is not valid."); 252 } 253 SiteInformation siteInfo = retrieveSite(properties, siteId); 254 m_sites.put(siteId, siteInfo); 255 m_siteIdsOrder.add(siteId); 256 } 257 } 258 } 259 260 267 public int getNumberOfSites() 268 { 269 return m_sites.size(); 270 } 271 272 279 public Iterator siteIdsIterator() 280 { 281 return m_siteIdsOrder.iterator(); 282 } 283 284 295 public SiteInformation getSite(String siteId) 296 { 297 return (SiteInformation) m_sites.get(siteId); 298 } 299 300 310 private boolean isValidSiteId(String text) 311 { 312 return Pattern.matches(VALID_SITE_ID_REGEX, text); 313 } 314 315 328 private SiteInformation retrieveSite(Properties properties, String siteId) 329 { 330 SiteInformation result; 331 332 String editorMarkerPrivilegeNamespace = getRequiredProperty(properties, siteId 333 + EDITOR_MARKER_PRIVILEGE_NAMESPACE_URI_PROPERTY_SUFFIX); 334 String editorMarkerPrivilegeName = getRequiredProperty(properties, siteId 335 + EDITOR_MARKER_PRIVILEGE_NAME_PROPERTY_SUFFIX); 336 result = new SiteInformation(siteId, editorMarkerPrivilegeNamespace, 337 editorMarkerPrivilegeName); 338 retrieveSiteNames(properties, result); 339 RepositoryInformation previewRepoInfo = retrieveRepositoryInformation(properties, result, 340 PREVIEW_REPOSITORY_ROLE_NAME); 341 result.setPreviewRepository(previewRepoInfo); 342 RepositoryInformation liveRepoInfo = retrieveRepositoryInformation(properties, result, 343 LIVE_REPOSITORY_ROLE_NAME); 344 result.setLiveRepository(liveRepoInfo); 345 346 return result; 347 } 348 349 360 private void retrieveSiteNames(Properties properties, SiteInformation siteInfo) 361 { 362 Pattern siteNamePattern = Pattern.compile(SITE_NAME_REGEX_PREFIX + siteInfo.getId() 363 + SITE_NAME_REGEX_SUFFIX); 364 Enumeration keysEnum = properties.keys(); 365 while (keysEnum.hasMoreElements()) 366 { 367 String key = (String ) keysEnum.nextElement(); 368 if (siteNamePattern.matcher(key).matches()) 369 { 370 siteInfo.addName(key.substring(key.length() - 2), properties.getProperty(key)); 371 } 372 } 373 } 374 375 391 private RepositoryInformation retrieveRepositoryInformation(Properties properties, 392 SiteInformation siteInfo, String repositoryRole) 393 { 394 RepositoryInformation result; 395 396 String propertyPrefix = siteInfo.getId() + REPOSITORY_PROPERTY_NAME_PART + repositoryRole 397 + '.'; 398 String host = getRequiredProperty(properties, propertyPrefix + HOST_PROPERTY_SUFFIX); 399 int port = getRequiredIntegerProperty(properties, propertyPrefix + PORT_PROPERTY_SUFFIX, 1, 400 65535); 401 String realm = getRequiredProperty(properties, propertyPrefix + REALM_PROPERTY_SUFFIX); 402 String username = getRequiredProperty(properties, propertyPrefix + USERNAME_PROPERTY_SUFFIX); 403 String password = getRequiredProperty(properties, propertyPrefix + PASSWORD_PROPERTY_SUFFIX); 404 String rootUri = getRequiredProperty(properties, propertyPrefix + ROOT_URI_PROPERTY_SUFFIX); 405 String baseUri = getRequiredProperty(properties, propertyPrefix + BASE_URI_PROPERTY_SUFFIX); 406 result = new RepositoryInformation(host, port, realm, username, password, rootUri, baseUri); 407 408 return result; 409 } 410 411 424 public static String getRequiredProperty(Properties properties, String propertyKey) 425 { 426 String result = properties.getProperty(propertyKey); 427 if (result == null || result.equals("")) 428 { 429 throw new IllegalArgumentException ("Property '" + propertyKey + "' is required."); 430 } 431 return result; 432 } 433 434 452 public static int getRequiredIntegerProperty(Properties properties, String propertyKey, 453 int minimumValue, int maximumValue) 454 { 455 int result; 456 457 String integerAsString = properties.getProperty(propertyKey); 458 if (integerAsString == null || integerAsString.equals("")) 459 { 460 throw new IllegalArgumentException ("Property '" + propertyKey 461 + "' is required and must be an integer in the range [" + minimumValue + ", " 462 + maximumValue + "]."); 463 } 464 try 465 { 466 result = Integer.parseInt(integerAsString); 467 } 468 catch (NumberFormatException e) 469 { 470 throw new IllegalArgumentException (createInvalidIntegerMessage(propertyKey, 471 minimumValue, maximumValue)); 472 } 473 if (!(result >= minimumValue && result <= maximumValue)) 474 { 475 throw new IllegalArgumentException (createInvalidIntegerMessage(propertyKey, 476 minimumValue, maximumValue)); 477 } 478 479 return result; 480 } 481 482 494 private static String createInvalidIntegerMessage(String propertyKey, int minimumValue, 495 int maximumValue) 496 { 497 return "Property '" + propertyKey + "' must be an integer in the range [" + minimumValue 498 + ", " + maximumValue + "]."; 499 } 500 } 501 | Popular Tags |