001/* 002 * Copyright 2011 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repositoryapp; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import javax.jcr.Credentials; 022import javax.jcr.Repository; 023import javax.jcr.RepositoryException; 024import javax.jcr.Session; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.context.ContextException; 028import org.apache.avalon.framework.context.Contextualizable; 029import org.apache.avalon.framework.logger.AbstractLogEnabled; 030import org.apache.cocoon.Constants; 031import org.apache.cocoon.components.ContextHelper; 032import org.apache.cocoon.environment.Context; 033import org.apache.jackrabbit.api.JackrabbitRepository; 034 035/** 036 * Repository helper. 037 */ 038public class RepositoryProvider extends AbstractLogEnabled implements Contextualizable, Component 039{ 040 /** The avalon role. */ 041 public static final String ROLE = RepositoryProvider.class.getName(); 042 043 /** The session map key. */ 044 public static final String SESSION_JCR_SESSIONS_KEY = "org.ametys.repository.Sessions"; 045 046 /** The context repository key. */ 047 public static final String CONTEXT_REPOSITORY_KEY = "org.ametys.repository.Repository"; 048 049 /** The JNDI variable key. */ 050 public static final String CONTEXT_IS_JNDI_KEY = "org.ametys.repository.JNDI"; 051 052 /** The credentials object key. */ 053 private static final String _CONTEXT_CREDENTIALS_KEY = "org.ametys.repository.Credentials"; 054 055 /** The avalon context, initialized during the contextualize method */ 056 private org.apache.avalon.framework.context.Context _avalonContext; 057 058 private Context _context; 059 060 @Override 061 public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException 062 { 063 _avalonContext = context; 064 _context = (Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 065 } 066 067 /** 068 * Get the repository. 069 * @return the repository. 070 */ 071 public Repository getRepository() 072 { 073 return (Repository) _context.getAttribute(CONTEXT_REPOSITORY_KEY); 074 } 075 076 /** 077 * Get the credentials. 078 * @return the credentials. 079 */ 080 public Credentials getCredentials() 081 { 082 return (Credentials) _context.getAttribute(_CONTEXT_CREDENTIALS_KEY); 083 } 084 085 /** 086 * Determines if the repository is obtained through JNDI 087 * @return true if the repository is obtained through JNDI 088 */ 089 public boolean isJndi() 090 { 091 return (Boolean) _context.getAttribute(CONTEXT_IS_JNDI_KEY); 092 } 093 094 /** 095 * Register a repository. 096 * @param repository The repository to register 097 * @param credentials The credentials to connect 098 * @param jndi True to connect using jndi 099 */ 100 public void registerRepository(Repository repository, Credentials credentials, boolean jndi) 101 { 102 _context.setAttribute(CONTEXT_REPOSITORY_KEY, repository); 103 _context.setAttribute(_CONTEXT_CREDENTIALS_KEY, credentials); 104 _context.setAttribute(CONTEXT_IS_JNDI_KEY, jndi); 105 } 106 107 /** 108 * Get the JCR session map. 109 * @return a Map of the JCR sessions, indexed by workspace name. 110 */ 111 @SuppressWarnings("unchecked") 112 public Map<String, Session> getSessions() 113 { 114 org.apache.cocoon.environment.Session httpSession = ContextHelper.getRequest(_avalonContext).getSession(); 115 116 Map<String, Session> sessions = (Map<String, Session>) httpSession.getAttribute(SESSION_JCR_SESSIONS_KEY); 117 if (sessions == null) 118 { 119 sessions = new HashMap<>(); 120 httpSession.setAttribute(SESSION_JCR_SESSIONS_KEY, sessions); 121 } 122 123 return sessions; 124 } 125 126 /** 127 * Get a session on the given workspace. 128 * @param workspaceName the workspace name. 129 * @return the JCR session. 130 * @throws RepositoryException if an error occurred 131 */ 132 public Session getSession(String workspaceName) throws RepositoryException 133 { 134 Map<String, Session> sessions = getSessions(); 135 136 Session session = sessions.get(workspaceName); 137 138 if (session == null || !session.isLive()) 139 { 140 Repository repository = getRepository(); 141 Credentials credentials = getCredentials(); 142 143 session = repository.login(credentials, workspaceName); 144 sessions.put(workspaceName, session); 145 } 146 147 return session; 148 } 149 150 /** 151 * Disconnect from the repository. 152 */ 153 public void disconnect() 154 { 155 // Logout all the sessions. 156 Map<String, Session> sessions = getSessions(); 157 for (Session session : sessions.values()) 158 { 159 session.logout(); 160 } 161 162 org.apache.cocoon.environment.Session httpSession = ContextHelper.getRequest(_avalonContext).getSession(); 163 httpSession.removeAttribute(SESSION_JCR_SESSIONS_KEY); 164 165 // We should test if the component manager knows the repository (embedded mode), 166 // and don't call shutdown in that case, but disconnect is called by LogoutAction, which is 167 // only present in standalone mode, so we should be fine. 168 Repository repository = getRepository(); 169 if (!isJndi() && repository instanceof JackrabbitRepository) 170 { 171 ((JackrabbitRepository) repository).shutdown(); 172 } 173 174 // Destroy the connection information. 175 _context.removeAttribute(CONTEXT_REPOSITORY_KEY); 176 _context.removeAttribute(_CONTEXT_CREDENTIALS_KEY); 177 _context.removeAttribute(CONTEXT_IS_JNDI_KEY); 178 } 179}