1 13 package info.magnolia.jackrabbit; 14 15 import info.magnolia.cms.beans.config.ContentRepository; 16 import info.magnolia.cms.beans.config.ShutdownManager; 17 import info.magnolia.cms.beans.config.ShutdownTask; 18 import info.magnolia.cms.core.Path; 19 import info.magnolia.repository.Provider; 20 import info.magnolia.repository.RepositoryMapping; 21 import info.magnolia.repository.RepositoryNotInitializedException; 22 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileNotFoundException ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.text.MessageFormat ; 29 import java.util.Hashtable ; 30 import java.util.Iterator ; 31 import java.util.Map ; 32 33 import javax.jcr.NamespaceException; 34 import javax.jcr.Repository; 35 import javax.jcr.RepositoryException; 36 import javax.jcr.Session; 37 import javax.jcr.SimpleCredentials; 38 import javax.jcr.Workspace; 39 import javax.jcr.nodetype.NoSuchNodeTypeException; 40 import javax.jcr.nodetype.NodeTypeManager; 41 import javax.naming.Context ; 42 import javax.naming.InitialContext ; 43 import javax.naming.NameNotFoundException ; 44 import javax.naming.NamingException ; 45 import javax.xml.transform.TransformerFactoryConfigurationError ; 46 47 import org.apache.commons.io.IOUtils; 48 import org.apache.commons.lang.ArrayUtils; 49 import org.apache.commons.lang.StringUtils; 50 import org.apache.commons.lang.SystemUtils; 51 import org.apache.jackrabbit.core.WorkspaceImpl; 52 import org.apache.jackrabbit.core.jndi.RegistryHelper; 53 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; 54 import org.apache.jackrabbit.core.nodetype.NodeTypeDef; 55 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl; 56 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; 57 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; 58 import org.slf4j.Logger; 59 import org.slf4j.LoggerFactory; 60 61 62 67 public class ProviderImpl implements Provider { 68 69 protected static Logger log = LoggerFactory.getLogger(ProviderImpl.class); 70 71 private static final String CONFIG_FILENAME_KEY = "configFile"; 73 private static final String REPOSITORY_HOME_KEY = "repositoryHome"; 75 private static final String CONTEXT_FACTORY_CLASS_KEY = "contextFactoryClass"; 77 private static final String PROVIDER_URL_KEY = "providerURL"; 79 private static final String BIND_NAME_KEY = "bindName"; 81 private static final String MGNL_NODETYPES = "/mgnl-nodetypes/magnolia-nodetypes.xml"; 83 private static final String CUSTOM_NODETYPES = "customNodeTypes"; 85 private RepositoryMapping repositoryMapping; 86 87 private Repository repository; 88 89 private static final String REPO_HOME_PREFIX = "${repository.home}"; 90 91 private static final int REPO_HOME_SUFIX_LEN = REPO_HOME_PREFIX.length(); 92 93 private static final String sysRepositoryHome = System.getProperty("repository.home"); 94 95 private static final String sysRepositoryHomes = System.getProperty("repository.homes"); 96 97 102 private String getRepositoryHome(final String repositoryHome) { 103 boolean relocate = false; 104 String tmp = repositoryHome; 105 if (repositoryHome.startsWith(REPOSITORY_HOME_KEY)) { 106 tmp = repositoryHome.substring(REPO_HOME_SUFIX_LEN); 107 relocate = true; 108 } 109 112 if (sysRepositoryHome != null && relocate) { 113 return sysRepositoryHome + File.separator + tmp; 114 } 115 116 119 if (sysRepositoryHomes != null) { 120 return sysRepositoryHomes + File.separator + tmp; 121 } 122 123 126 return Path.getAbsoluteFileSystemPath(tmp); 127 } 128 129 132 public void init(RepositoryMapping repositoryMapping) throws RepositoryNotInitializedException { 133 checkXmlSettings(); 134 135 this.repositoryMapping = repositoryMapping; 136 137 Map params = this.repositoryMapping.getParameters(); 138 String configFile = (String ) params.get(CONFIG_FILENAME_KEY); 139 configFile = Path.getAbsoluteFileSystemPath(configFile); 140 String repositoryHome = (String ) params.get(REPOSITORY_HOME_KEY); 141 repositoryHome = getRepositoryHome(repositoryHome); 142 if (log.isInfoEnabled()) { 143 log.info("Loading repository at {} (config file: {})", repositoryHome, configFile); } 145 String contextFactoryClass = (String ) params.get(CONTEXT_FACTORY_CLASS_KEY); 146 String providerURL = (String ) params.get(PROVIDER_URL_KEY); 147 boolean addShutdownTask = false; 148 final String bindName = (String ) params.get(BIND_NAME_KEY); 149 final Hashtable env = new Hashtable (); 150 env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClass); 151 env.put(Context.PROVIDER_URL, providerURL); 152 153 try { 154 InitialContext ctx = new InitialContext (env); 155 try { 157 this.repository = (Repository) ctx.lookup(bindName); 158 } 159 catch (NameNotFoundException ne) { 160 if (log.isDebugEnabled()) { 161 log.debug( 162 "No JNDI bound Repository found with name {} , trying to initialize a new Repository", 163 bindName); 164 } 165 RegistryHelper.registerRepository(ctx, bindName, configFile, repositoryHome, true); 166 this.repository = (Repository) ctx.lookup(bindName); 167 addShutdownTask = true; 168 } 169 this.validateWorkspaces(); 170 } 171 catch (NamingException e) { 172 log.error("Unable to initialize repository: " + e.getMessage(), e); 173 throw new RepositoryNotInitializedException(e); 174 } 175 catch (RepositoryException e) { 176 log.error("Unable to initialize repository: " + e.getMessage(), e); 177 throw new RepositoryNotInitializedException(e); 178 } 179 catch (TransformerFactoryConfigurationError e) { 180 log.error("Unable to initialize repository: " + e.getMessage(), e); 181 throw new RepositoryNotInitializedException(e); 182 } 183 184 if (addShutdownTask) { 185 ShutdownManager.addShutdownTask(new ShutdownTask() { 186 187 public boolean execute(info.magnolia.context.Context context) { 188 log.info("Shutting down repository bound to '{}'", bindName); 189 190 try { 191 Context ctx = new InitialContext (env); 192 RegistryHelper.unregisterRepository(ctx, bindName); 193 } 194 catch (NamingException ne) { 195 log.warn(MessageFormat.format("Unable to shutdown repository {0}: {1} {2}", new Object []{ 196 bindName, 197 ne.getClass().getName(), 198 ne.getMessage()}), ne); 199 } 200 catch (Throwable e) { 201 log.warn(MessageFormat.format("Failed to shutdown repository {0}: {1} {2}", new Object []{ 202 bindName, 203 e.getClass().getName(), 204 e.getMessage()}), e); 205 } 206 return true; 207 } 208 }); 209 } 210 } 211 212 215 public Repository getUnderlineRepository() throws RepositoryNotInitializedException { 216 if (this.repository == null) { 217 throw new RepositoryNotInitializedException("Null repository"); } 219 return this.repository; 220 } 221 222 225 public void registerNamespace(String namespacePrefix, String uri, Workspace workspace) throws RepositoryException { 226 try { 227 workspace.getNamespaceRegistry().getURI(namespacePrefix); 228 } 229 catch (NamespaceException e) { 230 if (log.isDebugEnabled()) { 231 log.debug(e.getMessage()); 232 } 233 log.info("registering prefix [{}] with uri {}", namespacePrefix, uri); workspace.getNamespaceRegistry().registerNamespace(namespacePrefix, uri); 235 } 236 } 237 238 241 public void unregisterNamespace(String prefix, Workspace workspace) throws RepositoryException { 242 workspace.getNamespaceRegistry().unregisterNamespace(prefix); 243 } 244 245 248 public void registerNodeTypes() throws RepositoryException { 249 registerNodeTypes(StringUtils.EMPTY); 250 } 251 252 255 public void registerNodeTypes(String configuration) throws RepositoryException { 256 if (StringUtils.isEmpty(configuration)) { 257 configuration = (String ) this.repositoryMapping.getParameters().get(CUSTOM_NODETYPES); 258 } 259 260 InputStream xml = getNodeTypeDefinition(configuration); 261 this.registerNodeTypes(xml); 262 } 263 264 267 public void registerNodeTypes(InputStream xmlStream) throws RepositoryException { 268 SimpleCredentials credentials = new SimpleCredentials( 269 ContentRepository.REPOSITORY_USER, 270 ContentRepository.REPOSITORY_PSWD.toCharArray()); 271 Session jcrSession = this.repository.login(credentials); 272 Workspace workspace = jcrSession.getWorkspace(); 273 274 if (xmlStream == null) { 276 throw new MissingNodetypesException(); 277 } 278 279 NodeTypeDef[] types; 280 try { 281 types = NodeTypeReader.read(xmlStream); 282 } 283 catch (InvalidNodeTypeDefException e) { 284 throw new RepositoryException(e.getMessage(), e); 285 } 286 catch (IOException e) { 287 throw new RepositoryException(e.getMessage(), e); 288 } 289 finally { 290 IOUtils.closeQuietly(xmlStream); 291 } 292 293 NodeTypeManager ntMgr = workspace.getNodeTypeManager(); 294 NodeTypeRegistry ntReg; 295 try { 296 ntReg = ((NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry(); 297 } catch (ClassCastException e) { 298 log.debug("Failed to get NodeTypeRegistry",e); 301 return; 302 } 303 304 for (int j = 0; j < types.length; j++) { 305 NodeTypeDef def = types[j]; 306 307 try { 308 ntReg.getNodeTypeDef(def.getName()); 309 } 310 catch (NoSuchNodeTypeException nsne) { 311 log.info("registering nodetype {}", def.getName()); 313 try { 314 ntReg.registerNodeType(def); 315 } 316 catch (InvalidNodeTypeDefException e) { 317 throw new RepositoryException(e.getMessage(), e); 318 } 319 catch (RepositoryException e) { 320 throw new RepositoryException(e.getMessage(), e); 321 } 322 } 323 324 } 325 } 326 327 331 private InputStream getNodeTypeDefinition(String configuration) { 332 333 InputStream xml; 334 335 if (StringUtils.isNotEmpty(configuration)) { 336 337 xml = getClass().getResourceAsStream(configuration); 339 if (xml != null) { 340 log.info("Custom node types registered using {}", configuration); 341 return xml; 342 } 343 344 File nodeTypeDefinition = new File (Path.getAbsoluteFileSystemPath(configuration)); 346 if (nodeTypeDefinition.exists()) { 347 try { 348 return new FileInputStream (nodeTypeDefinition); 349 } 350 catch (FileNotFoundException e) { 351 log.error("File not found: {}", xml); 353 } 354 } 355 356 log.error( 358 "Unable to find node type definition: {} for repository {}", 359 configuration, 360 this.repositoryMapping.getName()); 361 } 362 363 xml = getClass().getResourceAsStream(MGNL_NODETYPES); 365 366 return xml; 367 } 368 369 376 protected void checkXmlSettings() { 377 if (SystemUtils.isJavaVersionAtLeast(1.5f) 378 && "org.apache.xalan.processor.TransformerFactoryImpl".equals(System 379 .getProperty("javax.xml.transform.TransformerFactory"))) { 380 381 log.info("Java 1.5 detected, setting system property \"javax.xml.transform.TransformerFactory\" to " 382 + "\"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl\""); 383 384 System.setProperty( 385 "javax.xml.transform.TransformerFactory", 386 "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"); 387 } 388 } 389 390 393 private void validateWorkspaces() throws RepositoryException { 394 Iterator configuredNames = repositoryMapping.getWorkspaces().iterator(); 395 while (configuredNames.hasNext()) { 396 registerWorkspace((String ) configuredNames.next()); 397 } 398 } 399 400 403 public boolean registerWorkspace(String workspaceName) throws RepositoryException { 404 SimpleCredentials credentials = new SimpleCredentials( 406 ContentRepository.REPOSITORY_USER, 407 ContentRepository.REPOSITORY_PSWD.toCharArray()); 408 Session jcrSession = this.repository.login(credentials); 409 try { 410 WorkspaceImpl defaultWorkspace = (WorkspaceImpl) jcrSession.getWorkspace(); 411 String [] workspaceNames = defaultWorkspace.getAccessibleWorkspaceNames(); 412 413 boolean alreadyExists = ArrayUtils.contains(workspaceNames, workspaceName); 414 if (!alreadyExists) { 415 defaultWorkspace.createWorkspace(workspaceName); 416 } 417 jcrSession.logout(); 418 419 return !alreadyExists; 420 } catch (ClassCastException e) { 421 log.debug("Unable to register workspace, will continue", e); 424 } catch (Throwable t) { 425 log.error("Unable to register workspace, will continue", t); 426 } 427 return false; 428 } 429 430 } 431 | Popular Tags |